<commit_before>/*
  ReflectaArduinoCore.cpp - Library for exposing the core Arduino library functions over Reflecta
*/

#include "Reflecta.h"

using namespace reflecta;
using namespace reflectaFunctions;

namespace reflectaArduinoCore
{
  void pinMode()
  {
    ::pinMode(pop(), pop());
  }

  void digitalRead()
  {
    push(::digitalRead(pop()));
  }

  void digitalWrite()
  {
    ::digitalWrite(pop(), pop());
  }

  void analogRead()
  {
    push16(::analogRead(pop()));
  }

  void analogWrite()
  {
    ::analogWrite(pop(), pop());
  }

  void wireBeginMaster()
  {
    Wire.begin();
  }

  void wireRequestFrom()
  {
    Wire.requestFrom(pop(), pop());
  }

  void wireRequestFromStart()
  {
    Wire.requestFrom(pop(), pop(), false);
  }

  void wireAvailable()
  {
    push(Wire.available());
  }

  void wireRead()
  {
    if (Wire.available())
      push(Wire.read());
    else
      reflectaFrames::sendEvent(Error, WireNotAvailable);
  }

  void wireBeginTransmission()
  {
    Wire.beginTransmission(pop());
  }

  // TODO: Support variants write(string) and write(data, length)
  void wireWrite()
  {
    Wire.write(pop());
  }

  void wireEndTransmission()
  {
    Wire.endTransmission();
  }

  Servo servos[MAX_SERVOS];

  // TODO: Support variant attach(pin, min, max)
  void servoAttach()
  {
      int8_t pin = pop();
      servos[pin].attach(pin);
  }

  void servoDetach()
  {
      servos[pop()].detach();
  }

  void servoWrite()
  {
      servos[pop()].write(pop());
  }

  void servoWriteMicroseconds()
  {
      servos[pop()].writeMicroseconds(pop16());
  }

  // TODO: Support variant pulseIn(pin, value, timeout)
  void pulseIn()
  {
    // BUGBUG: Broken, returns a 32 bit result
    push(::pulseIn(pop(), pop()));
  }

  // Bind the Arduino core methods to the ardu1 interface
  void setup()
  {
    reflectaFunctions::bind("ardu1", pinMode);
    reflectaFunctions::bind("ardu1", digitalRead);
    reflectaFunctions::bind("ardu1", digitalWrite);
    reflectaFunctions::bind("ardu1", analogRead);
    reflectaFunctions::bind("ardu1", analogWrite);

    reflectaFunctions::bind("ardu1", wireBeginMaster);

    reflectaFunctions::bind("ardu1", wireRequestFrom);
    reflectaFunctions::bind("ardu1", wireRequestFromStart);
    reflectaFunctions::bind("ardu1", wireAvailable);
    reflectaFunctions::bind("ardu1", wireRead);

    reflectaFunctions::bind("ardu1", wireBeginTransmission);
    reflectaFunctions::bind("ardu1", wireWrite);
    reflectaFunctions::bind("ardu1", wireEndTransmission);

    reflectaFunctions::bind("ardu1", servoAttach);
    reflectaFunctions::bind("ardu1", servoDetach);
    reflectaFunctions::bind("ardu1", servoWrite);
    reflectaFunctions::bind("ardu1", servoWriteMicroseconds);

    reflectaFunctions::bind("ardu1", pulseIn);
  }
};
<commit_msg>Fix behavior changes in compiler that broke functionality in Arduino 1.5.x+<commit_after>/*
  ReflectaArduinoCore.cpp - Library for exposing the core Arduino library functions over Reflecta
*/

#include "Reflecta.h"

using namespace reflecta;
using namespace reflectaFunctions;

namespace reflectaArduinoCore
{
  void pinMode()
  {
    int8_t pin = pop();
    int8_t val = pop();
    ::pinMode(pin, val);
  }

  void digitalRead()
  {
    int8_t pin = pop();
    push(::digitalRead(pin));
  }

  void digitalWrite()
  {
    int8_t pin = pop();
    int8_t val = pop();
    ::digitalWrite(pin, val);
  }

  void analogRead()
  {
    int8_t pin = pop();
    push16(::analogRead(pin));
  }

  void analogWrite()
  {
    int8_t pin = pop();
    int8_t val = pop();
    ::analogWrite(pin, val);
  }

  void wireBeginMaster()
  {
    Wire.begin();
  }

  void wireRequestFrom()
  {
    int8_t address = pop();
    int8_t quantity = pop();
    Wire.requestFrom(address, quantity);
  }

  void wireRequestFromStart()
  {
    int8_t address = pop();
    int8_t quantity = pop();
    Wire.requestFrom(address, quantity, false);
  }

  void wireAvailable()
  {
    push(Wire.available());
  }

  void wireRead()
  {
    if (Wire.available())
      push(Wire.read());
    else
      reflectaFrames::sendEvent(Error, WireNotAvailable);
  }

  void wireBeginTransmission()
  {
    int8_t address = pop();
        Wire.beginTransmission(address);
  }

  // TODO: Support variants write(string) and write(data, length)
  void wireWrite()
  {
    int8_t val = pop();
    Wire.write(val);
  }

  void wireEndTransmission()
  {
    Wire.endTransmission();
  }

  Servo servos[MAX_SERVOS];

  // TODO: Support variant attach(pin, min, max)
  void servoAttach()
  {
      int8_t pin = pop();
      servos[pin].attach(pin);
  }

  void servoDetach()
  {
    int8_t pin = pop();
      servos[pin].detach();
  }

  void servoWrite()
  {
    int8_t pin = pop();
    int8_t val = pop();
      servos[pin].write(val);
  }

  void servoWriteMicroseconds()
  {
    int8_t pin = pop();
    int8_t val = pop16();
      servos[pin].writeMicroseconds(val);
  }

  // TODO: Support variant pulseIn(pin, value, timeout)
  void pulseIn()
  {
    // BUGBUG: Broken, returns a 32 bit result
    int8_t pin = pop();
    int8_t val = pop();
    push(::pulseIn(pin, val));
  }

  // Bind the Arduino core methods to the ardu1 interface
  void setup()
  {
    reflectaFunctions::bind("ardu1", pinMode);
    reflectaFunctions::bind("ardu1", digitalRead);
    reflectaFunctions::bind("ardu1", digitalWrite);
    reflectaFunctions::bind("ardu1", analogRead);
    reflectaFunctions::bind("ardu1", analogWrite);

    reflectaFunctions::bind("ardu1", wireBeginMaster);

    reflectaFunctions::bind("ardu1", wireRequestFrom);
    reflectaFunctions::bind("ardu1", wireRequestFromStart);
    reflectaFunctions::bind("ardu1", wireAvailable);
    reflectaFunctions::bind("ardu1", wireRead);

    reflectaFunctions::bind("ardu1", wireBeginTransmission);
    reflectaFunctions::bind("ardu1", wireWrite);
    reflectaFunctions::bind("ardu1", wireEndTransmission);

    reflectaFunctions::bind("ardu1", servoAttach);
    reflectaFunctions::bind("ardu1", servoDetach);
    reflectaFunctions::bind("ardu1", servoWrite);
    reflectaFunctions::bind("ardu1", servoWriteMicroseconds);

    reflectaFunctions::bind("ardu1", pulseIn);
  }
};
<|endoftext|>


<commit_before>/*
  LICENSE AND COPYRIGHT INFORMATION - Please read carefully.

  Copyright (c) 2010-2013, davyjones <dj@pgxplorer.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "querymodel.h"

QueryModel::QueryModel()
{
    this->rows_from = 1;
}

void QueryModel::setRowsFrom(int rows_from)
{
    this->rows_from = rows_from;
}

int QueryModel::getPivotCol()
{
    return this->pivot_col;
}

int QueryModel::getPivotCat()
{
    return this->pivot_cat;
}

int QueryModel::getPivotVal()
{
    return this->pivot_val;
}

void QueryModel::setPivotCol(int pivot_col)
{
    this->pivot_col = pivot_col;
}

void QueryModel::setPivotCat(int pivot_cat)
{
    this->pivot_cat = pivot_cat;
}

void QueryModel::setPivotVal(int pivot_val)
{
    this->pivot_val = pivot_val;
}

void QueryModel::setColumnAggregate(QStringList aggs)
{
    current_column_aggregates = aggs;
}

QVariant QueryModel::data(const QModelIndex &index, int role) const
{
    //Store the index into item to call the sibling of index.
    QModelIndex item = indexInQuery(index);

    //Align integers to the right
    if ((index.isValid() && role == Qt::TextAlignmentRole) && (index.data().type() != QMetaType::QString))
        return (Qt::AlignVCenter + Qt::AlignRight);

    if(index.isValid() && role == Qt::BackgroundRole && index.column() == pivot_col)
        return QColor(255, 0, 0, 100);

    if(index.isValid() && role == Qt::BackgroundRole && index.column() == pivot_cat)
        return QColor(0, 255, 0, 100);

    //Disable all roles except DisplayRole
    if (!index.isValid() || (role != Qt::DisplayRole))
        return QVariant();

    //Return sibling of index
    return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role);
}

QVariant QueryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Vertical && role == Qt::DisplayRole)
        return QVariant(rows_from + section);
    else
        return QSqlQueryModel::headerData(section, orientation, role);
}
<commit_msg>Initialise pivot values for QueryModel.<commit_after>/*
  LICENSE AND COPYRIGHT INFORMATION - Please read carefully.

  Copyright (c) 2010-2013, davyjones <dj@pgxplorer.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "querymodel.h"

QueryModel::QueryModel()
{
    this->rows_from = 1;

    pivot_col = -1;
    pivot_cat = -1;
    pivot_val = -1;
}

void QueryModel::setRowsFrom(int rows_from)
{
    this->rows_from = rows_from;
}

int QueryModel::getPivotCol()
{
    return this->pivot_col;
}

int QueryModel::getPivotCat()
{
    return this->pivot_cat;
}

int QueryModel::getPivotVal()
{
    return this->pivot_val;
}

void QueryModel::setPivotCol(int pivot_col)
{
    this->pivot_col = pivot_col;
}

void QueryModel::setPivotCat(int pivot_cat)
{
    this->pivot_cat = pivot_cat;
}

void QueryModel::setPivotVal(int pivot_val)
{
    this->pivot_val = pivot_val;
}

void QueryModel::setColumnAggregate(QStringList aggs)
{
    current_column_aggregates = aggs;
}

QVariant QueryModel::data(const QModelIndex &index, int role) const
{
    //Store the index into item to call the sibling of index.
    QModelIndex item = indexInQuery(index);

    //Align integers to the right
    if ((index.isValid() && role == Qt::TextAlignmentRole) && (index.data().type() != QMetaType::QString))
        return (Qt::AlignVCenter + Qt::AlignRight);

    if(index.isValid() && role == Qt::BackgroundRole && index.column() == pivot_col)
        return QColor(255, 0, 0, 100);

    if(index.isValid() && role == Qt::BackgroundRole && index.column() == pivot_cat)
        return QColor(0, 255, 0, 100);

    //Disable all roles except DisplayRole
    if (!index.isValid() || (role != Qt::DisplayRole))
        return QVariant();

    //Return sibling of index
    return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role);
}

QVariant QueryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Vertical && role == Qt::DisplayRole)
        return QVariant(rows_from + section);
    else
        return QSqlQueryModel::headerData(section, orientation, role);
}
<|endoftext|>


<commit_before>#include "core/stringutils.h"

#include <string>
#include <algorithm>
#include <cstring>
#include <vector>
#include <sstream>
#include <iterator>
#include <type_traits>

#include "core/assert.h"

namespace euphoria::core
{

std::pair<std::string, std::string>
last_strings(const std::string& str, char sep)
{
    auto result = str.find(sep);
    if(result == std::string::npos)
    {
        return std::make_pair(str, "");
    }

    const auto parent = str.substr(0, result);
    const auto child = str.substr(result, str.length() - parent.length());
    return std::make_pair(parent, child);
}

std::string
first_chars(const std::string& str, std::size_t count)
{
    if(str.length() < count) { return str; }
    else { return str.substr(0, count); }
}

std::string
first_chars_with_ellipsis(const std::string& str, unsigned int count)
{
    if (str.length() > count)
    {
        return str.substr(0, count) + "...";
    }

    return str;
}

std::string
strip_last_string(const std::string& str, char sep)
{
    auto result = str.find(sep);
    if(result == std::string::npos)
    {
        return "";
    }

    return str.substr(0, result);
}

std::string
trim_right(const std::string& string_to_trim, const std::string& trim_characters)
{
    return std::string(string_to_trim).erase(string_to_trim.find_last_not_of(trim_characters) + 1);
}

std::string
trim_left(const std::string& string_to_trim, const std::string& trim_characters)
{
    return std::string(string_to_trim).erase(0, string_to_trim.find_first_not_of(trim_characters));
}

std::string
trim(const std::string& string_to_trim, const std::string& trim_characters)
{
    return trim_right(trim_left(string_to_trim, trim_characters), trim_characters);
}

bool
starts_with(const std::string& string_to_test, const std::string& start)
{
    const std::string::size_type length = start.length();
    const std::string::size_type other_length = string_to_test.length();
    if(other_length < length)
    {
        return false;
    }
    const std::string actual_start = string_to_test.substr(0, length);
    return start == actual_start;
}

bool
ends_with(const std::string& string_to_test, const std::string& end)
{
    const std::string::size_type length = end.length();
    const std::string::size_type other_length = string_to_test.length();
    if(other_length < length)
    {
        return false;
    }
    const std::string actual_end
            = string_to_test.substr(other_length - length, length);
    return end == actual_end;
}

char
to_lower_char(char b)
{
    if(b >= 'A' && b <= 'Z')
    {
        return static_cast<char>((static_cast<int>(b) - 'A') + 'a');
    }
    else
    {
        return b;
    }
}

char
to_upper_char(char b)
{
    if(b >= 'a' && b <= 'z')
    {
        return static_cast<char>(b + ('A' - 'a'));
    }
    else
    {
        return b;
    }
}

std::string
to_lower(const std::string& str)
{
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), to_lower_char);
    return result;
}

std::vector<std::string>
to_lower(const std::vector<std::string>& str)
{
    return to_string_vector(str, [](const std::string& s) { return to_lower(s); });
}

std::string
to_upper(const std::string& str)
{
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), to_upper_char);
    return result;
}

std::string
char_to_string(char c, CharToStringStyle style)
{
    constexpr std::string_view smart_characters =
        "abcdefghijklmnopqrstuwxyz"
        "ABCDEFGHIJKLMNOPQRSTUWXYZ"
        " "
        "~!@#$%^&*()_+"
        "`123456790-="
        ",.<>/?"
        "{}[]:;\"'\\|"
        "\n\r\t"
        ;
    std::ostringstream ss;
    switch(c)
    {
    case 0:
        ss << "<null>";
        if(style == CharToStringStyle::smart)
        {
            return ss.str();
        }
        break;
    case '\n':
        ss << "<\\n>";
        break;
    case '\r':
        ss << "<\\r>";
        break;
    case '\t':
        ss << "<tab>";
        break;
    // source: http://www.asciitable.com/
    case  1: ss << "<start of heading>"; break;
    case  2: ss << "<start of text>"; break;
    case  3: ss << "<end of text>"; break;
    case  4: ss << "<end of transmission>"; break;
    case  5: ss << "<enquiry>"; break;
    case  6: ss << "<acknowledge>"; break;
    case  7: ss << "<bell>"; break;
    case  8: ss << "<backspace>"; break;
    // case  9: ss << "<horizontal tab>"; break;
    // case 10: ss << "<newline>"; break;
    case 11: ss << "<vertical tab>"; break;
    case 12: ss << "<new page>"; break;
    // case 13: ss << "<carriage return>"; break;
    case 14: ss << "<shift out>"; break;
    case 15: ss << "<shift in>"; break;
    case 16: ss << "<data link esqape>"; break;
    case 17: ss << "<device control 1>"; break;
    case 18: ss << "<device control 2>"; break;
    case 19: ss << "<device control 3>"; break;
    case 20: ss << "<device control 4>"; break;
    case 21: ss << "<negative acknowledge>"; break;
    case 22: ss << "<synchronous idle>"; break;
    case 23: ss << "<end of trans. block>"; break;
    case 24: ss << "<cancel>"; break;
    case 25: ss << "<end of medium>"; break;
    case 26: ss << "<substitute>"; break;
    case 27: ss << "<escape>"; break;
    case 28: ss << "<file separator>"; break;
    case 29: ss << "<group separator>"; break;
    case 30: ss << "<record separator>"; break;
    case 31: ss << "<unit separator>"; break;
    case 127: ss << "<DEL>"; break;

    case ' ':
        ss << "<space>";
        break;
    default:
        ss << c;
        break;
    }

    if(style == CharToStringStyle::include_hex || smart_characters.find(c) == std::string_view::npos)
    {
        ss << "(0x" << std::hex << static_cast<int>(c) << ")";
    }
    return ss.str();
}

std::string::size_type
find_first_index_of_mismatch(const std::string& lhs, const std::string& rhs)
{
    const auto end = std::min(lhs.size(), rhs.size());

    std::string::size_type index = 0;
    for(; index < end; index+=1)
    {
        if(lhs[index]!=rhs[index])
        {
            return index;
        }
    }

    if(index >= lhs.size() && index >= rhs.size())
    {
        return std::string::npos;
    }
    else
    {
        return end;
    }
}

void
replace_all(std::string* string, const std::string& to_find, const std::string& to_replace)
{
    std::size_t index = string->find(to_find);
    const std::size_t find_length = to_find.length();
    ASSERT(find_length > 0);
    while(index != std::string::npos)
    {
        string->erase(index, find_length);
        string->insert(index, to_replace);
        index = string->find(to_find, index);
    }
}

std::string
replace_all(const std::string& string, const std::string& to_find, const std::string& to_replace)
{
    std::string temp = string;
    replace_all(&temp, to_find, to_replace);
    return temp;
}

void
copy(char* dst, const std::string& src, const std::string::size_type& count)
{
    strncpy(dst, src.c_str(), count - 1);
    dst[count - 1] = 0;
}

std::string
replace_with_character(const std::string& string, const std::string& to_find, char to_replace)
{
    std::string s = string;
    for(char c: to_find)
    {
        std::replace(s.begin(), s.end(), c, to_replace);
    }
    return s;
}

std::string
remove_from_end(const std::string& str, const std::string& end)
{
    if(ends_with(str, end))
    {
        const auto new_length = str.length() - end.length();
        if(new_length == 0)
        {
            return "";
        }
        ASSERT(new_length > 0);
        return str.substr(0, new_length);
    }

    return str;
}

std::string
strip(const std::string& str, const std::string& ch)
{
    std::stringstream ss;
    for(const char c: str)
    {
        if(ch.find(c) == std::string::npos)
        {
            ss << c;
        }
    }
    return ss.str();
}

// remove all characters in ch except the first one in a chain from str
std::string
remove_consecutive(const std::string& str, const std::string& ch)
{
    std::stringstream ss;
    bool skip = false;
    for(const char c: str)
    {
        if(ch.find(c) == std::string::npos)
        {
            ss << c;
            skip = false;
        }
        else
        {
            if(!skip)
            {
                ss << c;
                skip = true;
            }
        }
    }
    return ss.str();
}

namespace
{
    template<typename R, typename T>
    struct SizeGetter
    {
        static R get(const T& t) { return t.size(); }
    };

    template<typename R>
    struct SizeGetter<R, char>
    {
        static R get(char) { return 1; }
    };

    template<typename R, typename T>
    R get_size(const T& t) { return SizeGetter<R, T>::get(t); }

    template
    <
        typename ListType,
        typename OffsetType,
        typename StringType,
        typename DelimType,
        typename AddFunction
    >
    ListType
    split_base(const StringType str, DelimType delim, bool add_final, AddFunction&& add_function)
    {
        ListType ret;

        const OffsetType delim_length = get_size<OffsetType>(delim);

        OffsetType search_start = 0;
        OffsetType index = 0;

        while(true)
        {
            const auto found_index = str.find(delim, search_start);
            if(found_index == StringType::npos)
            {
                // abort... add last?
                // todo(Gustav): add argument to specify how to handle split on empty input
                if(add_final && str.empty() == false)
                {
                    add_function(ret, index, str.substr(search_start));
                }
                return ret;
            }
            add_function(ret, index, str.substr(search_start, found_index - search_start));
            index += 1;
            search_start = found_index + delim_length;
        }
    }
}

std::vector<std::string>
split(const std::string& s, char c)
{
    return split_base<std::vector<std::string>, std::size_t>
    (
        s, c, true, [](std::vector<std::string>& v, std::size_t, const std::string& s)
        {
            v.emplace_back(s);
        }
    );
}

std::vector<std::string>
split_on_spaces(const std::string& string)
{
    std::istringstream iss(string);
    return std::vector<std::string>
    (
        std::istream_iterator<std::string>{iss},
        std::istream_iterator<std::string>()
    );
}

std::string
optional_string(bool b, const std::string& str)
{
    if(b)
    {
        return str;
    }
    else
    {
        return "";
    }
}

bool
is_number(char b)
{
    return b >= '0' && b <= '9';
}

int
parse_number(const char** aa)
{
    const char*& a = *aa;

    int result = *a - '0';
    ++a;

    while(is_number(*a))
    {
        result *= 10;
        result += *a - '0';
        ++a;
    }

    --a;
    return result;
}

int
string_compare(const std::string& lhs, const std::string& rhs)
{
    const char* a = lhs.c_str();
    const char* b = rhs.c_str();

    if(a == b)    { return  0; }
    if(a == nullptr) { return -1; }
    if(b == nullptr) { return  1; }

    while(*a != 0 && *b != 0)
    {
        // will contain either a number or a letter
        const int a0 = is_number(*a) ? parse_number(&a) + 256 : to_lower_char(*a);
        const int b0 = is_number(*b) ? parse_number(&b) + 256 : to_lower_char(*b);

        if(a0 < b0) { return -1; }
        if(a0 > b0) { return  1; }

        ++a;
        ++b;
    }

    if(*a != 0) { return  1; }
    if(*b != 0) { return -1; }

    return 0;
}

}
<commit_msg>fix: use auto to fix clang-tidy error<commit_after>#include "core/stringutils.h"

#include <string>
#include <algorithm>
#include <cstring>
#include <vector>
#include <sstream>
#include <iterator>
#include <type_traits>

#include "core/assert.h"

namespace euphoria::core
{

std::pair<std::string, std::string>
last_strings(const std::string& str, char sep)
{
    auto result = str.find(sep);
    if(result == std::string::npos)
    {
        return std::make_pair(str, "");
    }

    const auto parent = str.substr(0, result);
    const auto child = str.substr(result, str.length() - parent.length());
    return std::make_pair(parent, child);
}

std::string
first_chars(const std::string& str, std::size_t count)
{
    if(str.length() < count) { return str; }
    else { return str.substr(0, count); }
}

std::string
first_chars_with_ellipsis(const std::string& str, unsigned int count)
{
    if (str.length() > count)
    {
        return str.substr(0, count) + "...";
    }

    return str;
}

std::string
strip_last_string(const std::string& str, char sep)
{
    auto result = str.find(sep);
    if(result == std::string::npos)
    {
        return "";
    }

    return str.substr(0, result);
}

std::string
trim_right(const std::string& string_to_trim, const std::string& trim_characters)
{
    return std::string(string_to_trim).erase(string_to_trim.find_last_not_of(trim_characters) + 1);
}

std::string
trim_left(const std::string& string_to_trim, const std::string& trim_characters)
{
    return std::string(string_to_trim).erase(0, string_to_trim.find_first_not_of(trim_characters));
}

std::string
trim(const std::string& string_to_trim, const std::string& trim_characters)
{
    return trim_right(trim_left(string_to_trim, trim_characters), trim_characters);
}

bool
starts_with(const std::string& string_to_test, const std::string& start)
{
    const std::string::size_type length = start.length();
    const std::string::size_type other_length = string_to_test.length();
    if(other_length < length)
    {
        return false;
    }
    const std::string actual_start = string_to_test.substr(0, length);
    return start == actual_start;
}

bool
ends_with(const std::string& string_to_test, const std::string& end)
{
    const std::string::size_type length = end.length();
    const std::string::size_type other_length = string_to_test.length();
    if(other_length < length)
    {
        return false;
    }
    const std::string actual_end
            = string_to_test.substr(other_length - length, length);
    return end == actual_end;
}

char
to_lower_char(char b)
{
    if(b >= 'A' && b <= 'Z')
    {
        return static_cast<char>((static_cast<int>(b) - 'A') + 'a');
    }
    else
    {
        return b;
    }
}

char
to_upper_char(char b)
{
    if(b >= 'a' && b <= 'z')
    {
        return static_cast<char>(b + ('A' - 'a'));
    }
    else
    {
        return b;
    }
}

std::string
to_lower(const std::string& str)
{
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), to_lower_char);
    return result;
}

std::vector<std::string>
to_lower(const std::vector<std::string>& str)
{
    return to_string_vector(str, [](const std::string& s) { return to_lower(s); });
}

std::string
to_upper(const std::string& str)
{
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(), to_upper_char);
    return result;
}

std::string
char_to_string(char c, CharToStringStyle style)
{
    constexpr std::string_view smart_characters =
        "abcdefghijklmnopqrstuwxyz"
        "ABCDEFGHIJKLMNOPQRSTUWXYZ"
        " "
        "~!@#$%^&*()_+"
        "`123456790-="
        ",.<>/?"
        "{}[]:;\"'\\|"
        "\n\r\t"
        ;
    std::ostringstream ss;
    switch(c)
    {
    case 0:
        ss << "<null>";
        if(style == CharToStringStyle::smart)
        {
            return ss.str();
        }
        break;
    case '\n':
        ss << "<\\n>";
        break;
    case '\r':
        ss << "<\\r>";
        break;
    case '\t':
        ss << "<tab>";
        break;
    // source: http://www.asciitable.com/
    case  1: ss << "<start of heading>"; break;
    case  2: ss << "<start of text>"; break;
    case  3: ss << "<end of text>"; break;
    case  4: ss << "<end of transmission>"; break;
    case  5: ss << "<enquiry>"; break;
    case  6: ss << "<acknowledge>"; break;
    case  7: ss << "<bell>"; break;
    case  8: ss << "<backspace>"; break;
    // case  9: ss << "<horizontal tab>"; break;
    // case 10: ss << "<newline>"; break;
    case 11: ss << "<vertical tab>"; break;
    case 12: ss << "<new page>"; break;
    // case 13: ss << "<carriage return>"; break;
    case 14: ss << "<shift out>"; break;
    case 15: ss << "<shift in>"; break;
    case 16: ss << "<data link esqape>"; break;
    case 17: ss << "<device control 1>"; break;
    case 18: ss << "<device control 2>"; break;
    case 19: ss << "<device control 3>"; break;
    case 20: ss << "<device control 4>"; break;
    case 21: ss << "<negative acknowledge>"; break;
    case 22: ss << "<synchronous idle>"; break;
    case 23: ss << "<end of trans. block>"; break;
    case 24: ss << "<cancel>"; break;
    case 25: ss << "<end of medium>"; break;
    case 26: ss << "<substitute>"; break;
    case 27: ss << "<escape>"; break;
    case 28: ss << "<file separator>"; break;
    case 29: ss << "<group separator>"; break;
    case 30: ss << "<record separator>"; break;
    case 31: ss << "<unit separator>"; break;
    case 127: ss << "<DEL>"; break;

    case ' ':
        ss << "<space>";
        break;
    default:
        ss << c;
        break;
    }

    if(style == CharToStringStyle::include_hex || smart_characters.find(c) == std::string_view::npos)
    {
        ss << "(0x" << std::hex << static_cast<int>(c) << ")";
    }
    return ss.str();
}

std::string::size_type
find_first_index_of_mismatch(const std::string& lhs, const std::string& rhs)
{
    const auto end = std::min(lhs.size(), rhs.size());

    std::string::size_type index = 0;
    for(; index < end; index+=1)
    {
        if(lhs[index]!=rhs[index])
        {
            return index;
        }
    }

    if(index >= lhs.size() && index >= rhs.size())
    {
        return std::string::npos;
    }
    else
    {
        return end;
    }
}

void
replace_all(std::string* string, const std::string& to_find, const std::string& to_replace)
{
    std::size_t index = string->find(to_find);
    const std::size_t find_length = to_find.length();
    ASSERT(find_length > 0);
    while(index != std::string::npos)
    {
        string->erase(index, find_length);
        string->insert(index, to_replace);
        index = string->find(to_find, index);
    }
}

std::string
replace_all(const std::string& string, const std::string& to_find, const std::string& to_replace)
{
    std::string temp = string;
    replace_all(&temp, to_find, to_replace);
    return temp;
}

void
copy(char* dst, const std::string& src, const std::string::size_type& count)
{
    strncpy(dst, src.c_str(), count - 1);
    dst[count - 1] = 0;
}

std::string
replace_with_character(const std::string& string, const std::string& to_find, char to_replace)
{
    std::string s = string;
    for(char c: to_find)
    {
        std::replace(s.begin(), s.end(), c, to_replace);
    }
    return s;
}

std::string
remove_from_end(const std::string& str, const std::string& end)
{
    if(ends_with(str, end))
    {
        const auto new_length = str.length() - end.length();
        if(new_length == 0)
        {
            return "";
        }
        ASSERT(new_length > 0);
        return str.substr(0, new_length);
    }

    return str;
}

std::string
strip(const std::string& str, const std::string& ch)
{
    std::stringstream ss;
    for(const char c: str)
    {
        if(ch.find(c) == std::string::npos)
        {
            ss << c;
        }
    }
    return ss.str();
}

// remove all characters in ch except the first one in a chain from str
std::string
remove_consecutive(const std::string& str, const std::string& ch)
{
    std::stringstream ss;
    bool skip = false;
    for(const char c: str)
    {
        if(ch.find(c) == std::string::npos)
        {
            ss << c;
            skip = false;
        }
        else
        {
            if(!skip)
            {
                ss << c;
                skip = true;
            }
        }
    }
    return ss.str();
}

namespace
{
    template<typename R, typename T>
    struct SizeGetter
    {
        static R get(const T& t) { return t.size(); }
    };

    template<typename R>
    struct SizeGetter<R, char>
    {
        static R get(char) { return 1; }
    };

    template<typename R, typename T>
    R get_size(const T& t) { return SizeGetter<R, T>::get(t); }

    template
    <
        typename ListType,
        typename OffsetType,
        typename StringType,
        typename DelimType,
        typename AddFunction
    >
    ListType
    split_base(const StringType str, DelimType delim, bool add_final, AddFunction&& add_function)
    {
        ListType ret;

        const auto delim_length = get_size<OffsetType>(delim);

        OffsetType search_start = 0;
        OffsetType index = 0;

        while(true)
        {
            const auto found_index = str.find(delim, search_start);
            if(found_index == StringType::npos)
            {
                // abort... add last?
                // todo(Gustav): add argument to specify how to handle split on empty input
                if(add_final && str.empty() == false)
                {
                    add_function(ret, index, str.substr(search_start));
                }
                return ret;
            }
            add_function(ret, index, str.substr(search_start, found_index - search_start));
            index += 1;
            search_start = found_index + delim_length;
        }
    }
}

std::vector<std::string>
split(const std::string& s, char c)
{
    return split_base<std::vector<std::string>, std::size_t>
    (
        s, c, true, [](std::vector<std::string>& v, std::size_t, const std::string& s)
        {
            v.emplace_back(s);
        }
    );
}

std::vector<std::string>
split_on_spaces(const std::string& string)
{
    std::istringstream iss(string);
    return std::vector<std::string>
    (
        std::istream_iterator<std::string>{iss},
        std::istream_iterator<std::string>()
    );
}

std::string
optional_string(bool b, const std::string& str)
{
    if(b)
    {
        return str;
    }
    else
    {
        return "";
    }
}

bool
is_number(char b)
{
    return b >= '0' && b <= '9';
}

int
parse_number(const char** aa)
{
    const char*& a = *aa;

    int result = *a - '0';
    ++a;

    while(is_number(*a))
    {
        result *= 10;
        result += *a - '0';
        ++a;
    }

    --a;
    return result;
}

int
string_compare(const std::string& lhs, const std::string& rhs)
{
    const char* a = lhs.c_str();
    const char* b = rhs.c_str();

    if(a == b)    { return  0; }
    if(a == nullptr) { return -1; }
    if(b == nullptr) { return  1; }

    while(*a != 0 && *b != 0)
    {
        // will contain either a number or a letter
        const int a0 = is_number(*a) ? parse_number(&a) + 256 : to_lower_char(*a);
        const int b0 = is_number(*b) ? parse_number(&b) + 256 : to_lower_char(*b);

        if(a0 < b0) { return -1; }
        if(a0 > b0) { return  1; }

        ++a;
        ++b;
    }

    if(*a != 0) { return  1; }
    if(*b != 0) { return -1; }

    return 0;
}

}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkMapper.h"
#include "vtkLookupTable.h"

// Initialize static member that controls global immediate mode rendering
static int vtkMapperGlobalImmediateModeRendering = 0;

// Initialize static member that controls global coincidence resolution
static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0;

// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Colors = NULL;

  this->LookupTable = NULL;

  this->ScalarVisibility = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;
  this->UseLookupTableScalarRange = 0;

  this->ImmediateModeRendering = 0;

  this->ColorMode = VTK_COLOR_MODE_DEFAULT;
  this->ScalarMode = VTK_SCALAR_MODE_DEFAULT;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = -1.0;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = 1.0;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;

  this->RenderTime = 0.0;

  strcpy(this->ArrayName, "");
  this->ArrayId = -1;
  this->ArrayComponent = -1;
  this->ArrayAccessMode = -1;
}

vtkMapper::~vtkMapper()
{
  if (this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  if ( this->Colors != NULL )
    {
    this->Colors->UnRegister(this);
    }
}

// Get the bounds for the input of this mapper as
// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->GetInput() )
    {
    return bounds;
    }
  else
    {
    this->Update();
    this->GetInput()->GetBounds(this->Bounds);
    return this->Bounds;
    }
}

vtkDataSet *vtkMapper::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkDataSet *)(this->Inputs[0]);
}

void vtkMapper::SetGlobalImmediateModeRendering(int val)
{
  if (val == vtkMapperGlobalImmediateModeRendering)
    {
    return;
    }
  vtkMapperGlobalImmediateModeRendering = val;
}

int vtkMapper::GetGlobalImmediateModeRendering()
{
  return vtkMapperGlobalImmediateModeRendering;
}

void vtkMapper::SetResolveCoincidentTopology(int val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopology)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopology = val;
}

int vtkMapper::GetResolveCoincidentTopology()
{
  return vtkMapperGlobalResolveCoincidentTopology;
}

void vtkMapper::SetResolveCoincidentTopologyToDefault()
{
  vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
}

void vtkMapper::SetResolveCoincidentTopologyZShift(double val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopologyZShift)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyZShift = val;
}

double vtkMapper::GetResolveCoincidentTopologyZShift()
{
  return vtkMapperGlobalResolveCoincidentTopologyZShift;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(
                                            float factor, float units)
{
  if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor &&
      units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits )
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor;
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = units;
}

void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(
                           float& factor, float& units)
{
  factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor;
  units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits;
}

// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::ShallowCopy(vtkMapper *m)
{
  this->SetLookupTable(m->GetLookupTable());
  this->SetClippingPlanes(m->GetClippingPlanes());
  this->SetScalarVisibility(m->GetScalarVisibility());
  this->SetScalarRange(m->GetScalarRange());
  this->SetColorMode(m->GetColorMode());
  this->SetScalarMode(m->GetScalarMode());
  this->SetImmediateModeRendering(m->GetImmediateModeRendering());
}

// a side effect of this is that this->Colors is also set
// to the return value
vtkScalars *vtkMapper::GetColors()
{
  vtkScalars *scalars = NULL;
  vtkDataArray *dataArray=0;
  vtkPointData *pd;
  vtkCellData *cd;
  vtkIdType i, numScalars;

  // make sure we have an input
  if (!this->GetInput())
    {
    return NULL;
    }

  // get and scalar data according to scalar mode
  if ( this->ScalarMode == VTK_SCALAR_MODE_DEFAULT )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    if (!scalars)
      {
      scalars = this->GetInput()->GetCellData()->GetScalars();
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    scalars = this->GetInput()->GetCellData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    pd = this->GetInput()->GetPointData();
    if (pd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = pd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = pd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    cd = this->GetInput()->GetCellData();
    if (cd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = cd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = cd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    }

  // do we have any scalars ?
  if (scalars && this->ScalarVisibility)
    {
    // if the scalars have a lookup table use it instead
    if (scalars->GetLookupTable())
      {
      this->SetLookupTable(scalars->GetLookupTable());
      }
    else
      {
      // make sure we have a lookup table
      if ( this->LookupTable == NULL )
	      {
	      this->CreateDefaultLookupTable();
	      }
      this->LookupTable->Build();
      }

    // Setup mapper/scalar object for color generation
    if (!this->UseLookupTableScalarRange)
      {
      this->LookupTable->SetRange(this->ScalarRange);
      }

    if (this->Colors)
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = scalars;
    this->Colors->Register(this);
    this->Colors->InitColorTraversal(1.0, this->LookupTable, this->ColorMode);
    }

  else //scalars not visible
    {
    if ( this->Colors )
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = NULL;
    }

  if (((this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) ||
       (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA)) &&
      scalars)
    {
    scalars->Delete();
    }

  return this->Colors;
}

void vtkMapper::ColorByArrayComponent(int arrayNum, int component)
{
  if (this->ArrayId == arrayNum && component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  this->ArrayId = arrayNum;
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
}

void vtkMapper::ColorByArrayComponent(char* arrayName, int component)
{
  if (strcmp(this->ArrayName, arrayName) == 0 &&
      component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  strcpy(this->ArrayName, arrayName);
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME;
}

// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkScalarsToColors *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->LookupTable)
      {
      this->LookupTable->UnRegister(this);
      }
    this->LookupTable = lut;
    if (lut)
      {
      lut->Register(this);
      }
    this->Modified();
    }
}

vtkScalarsToColors *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL )
    {
    this->CreateDefaultLookupTable();
    }
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  this->LookupTable = vtkLookupTable::New();
}

// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->GetInput() )
    {
    this->GetInput()->Update();
    }
}

// Return the method of coloring scalar data.
const char *vtkMapper::GetColorModeAsString(void)
{
  if ( this->ColorMode == VTK_COLOR_MODE_LUMINANCE )
    {
    return "Luminance";
    }
  else if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS )
    {
    return "MapScalars";
    }
  else
    {
    return "Default";
    }
}

// Return the method for obtaining scalar data.
const char *vtkMapper::GetScalarModeAsString(void)
{
  if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    return "UseCellData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    return "UsePointData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    return "UsePointFieldData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    return "UseCellFieldData";
    }
  else
    {
    return "Default";
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkAbstractMapper3D::PrintSelf(os,indent);

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

  os << indent << "Immediate Mode Rendering: "
    << (this->ImmediateModeRendering ? "On\n" : "Off\n");
  os << indent << "Global Immediate Mode Rendering: " <<
    (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n");

  os << indent << "Scalar Visibility: "
    << (this->ScalarVisibility ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";

  os << indent << "UseLookupTableScalarRange: " << this->UseLookupTableScalarRange << "\n";

  os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;

  os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl;

  os << indent << "RenderTime: " << this->RenderTime << endl;

  os << indent << "Resolve Coincident Topology: ";
  if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF )
    {
    os << "Off" << endl;
    }
  else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET )
    {
    os << "Polygon Offset" << endl;
    }
  else
    {
    os << "Shift Z-Buffer" << endl;
    }
}
<commit_msg>ENH:Notify the user that the indicated data array was not found when performing scalar coloring<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkMapper.h"
#include "vtkLookupTable.h"

// Initialize static member that controls global immediate mode rendering
static int vtkMapperGlobalImmediateModeRendering = 0;

// Initialize static member that controls global coincidence resolution
static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0;

// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Colors = NULL;

  this->LookupTable = NULL;

  this->ScalarVisibility = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;
  this->UseLookupTableScalarRange = 0;

  this->ImmediateModeRendering = 0;

  this->ColorMode = VTK_COLOR_MODE_DEFAULT;
  this->ScalarMode = VTK_SCALAR_MODE_DEFAULT;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = -1.0;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = 1.0;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;

  this->RenderTime = 0.0;

  strcpy(this->ArrayName, "");
  this->ArrayId = -1;
  this->ArrayComponent = -1;
  this->ArrayAccessMode = -1;
}

vtkMapper::~vtkMapper()
{
  if (this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  if ( this->Colors != NULL )
    {
    this->Colors->UnRegister(this);
    }
}

// Get the bounds for the input of this mapper as
// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->GetInput() )
    {
    return bounds;
    }
  else
    {
    this->Update();
    this->GetInput()->GetBounds(this->Bounds);
    return this->Bounds;
    }
}

vtkDataSet *vtkMapper::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkDataSet *)(this->Inputs[0]);
}

void vtkMapper::SetGlobalImmediateModeRendering(int val)
{
  if (val == vtkMapperGlobalImmediateModeRendering)
    {
    return;
    }
  vtkMapperGlobalImmediateModeRendering = val;
}

int vtkMapper::GetGlobalImmediateModeRendering()
{
  return vtkMapperGlobalImmediateModeRendering;
}

void vtkMapper::SetResolveCoincidentTopology(int val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopology)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopology = val;
}

int vtkMapper::GetResolveCoincidentTopology()
{
  return vtkMapperGlobalResolveCoincidentTopology;
}

void vtkMapper::SetResolveCoincidentTopologyToDefault()
{
  vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
}

void vtkMapper::SetResolveCoincidentTopologyZShift(double val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopologyZShift)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyZShift = val;
}

double vtkMapper::GetResolveCoincidentTopologyZShift()
{
  return vtkMapperGlobalResolveCoincidentTopologyZShift;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(
                                            float factor, float units)
{
  if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor &&
      units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits )
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor;
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = units;
}

void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(
                           float& factor, float& units)
{
  factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor;
  units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits;
}

// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::ShallowCopy(vtkMapper *m)
{
  this->SetLookupTable(m->GetLookupTable());
  this->SetClippingPlanes(m->GetClippingPlanes());
  this->SetScalarVisibility(m->GetScalarVisibility());
  this->SetScalarRange(m->GetScalarRange());
  this->SetColorMode(m->GetColorMode());
  this->SetScalarMode(m->GetScalarMode());
  this->SetImmediateModeRendering(m->GetImmediateModeRendering());
}

// a side effect of this is that this->Colors is also set
// to the return value
vtkScalars *vtkMapper::GetColors()
{
  vtkScalars *scalars = NULL;
  vtkDataArray *dataArray=0;
  vtkPointData *pd;
  vtkCellData *cd;
  vtkIdType i, numScalars;

  // make sure we have an input
  if (!this->GetInput())
    {
    return NULL;
    }

  // get and scalar data according to scalar mode
  if ( this->ScalarMode == VTK_SCALAR_MODE_DEFAULT )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    if (!scalars)
      {
      scalars = this->GetInput()->GetCellData()->GetScalars();
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    scalars = this->GetInput()->GetCellData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    pd = this->GetInput()->GetPointData();
    if (pd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = pd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = pd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    cd = this->GetInput()->GetCellData();
    if (cd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = cd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = cd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }

  // do we have any scalars ?
  if (scalars && this->ScalarVisibility)
    {
    // if the scalars have a lookup table use it instead
    if (scalars->GetLookupTable())
      {
      this->SetLookupTable(scalars->GetLookupTable());
      }
    else
      {
      // make sure we have a lookup table
      if ( this->LookupTable == NULL )
	      {
	      this->CreateDefaultLookupTable();
	      }
      this->LookupTable->Build();
      }

    // Setup mapper/scalar object for color generation
    if (!this->UseLookupTableScalarRange)
      {
      this->LookupTable->SetRange(this->ScalarRange);
      }

    if (this->Colors)
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = scalars;
    this->Colors->Register(this);
    this->Colors->InitColorTraversal(1.0, this->LookupTable, this->ColorMode);
    }

  else //scalars not visible
    {
    if ( this->Colors )
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = NULL;
    }

  if (((this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) ||
       (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA)) &&
      scalars)
    {
    scalars->Delete();
    }

  return this->Colors;
}

void vtkMapper::ColorByArrayComponent(int arrayNum, int component)
{
  if (this->ArrayId == arrayNum && component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  this->ArrayId = arrayNum;
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
}

void vtkMapper::ColorByArrayComponent(char* arrayName, int component)
{
  if (strcmp(this->ArrayName, arrayName) == 0 &&
      component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  strcpy(this->ArrayName, arrayName);
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME;
}

// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkScalarsToColors *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->LookupTable)
      {
      this->LookupTable->UnRegister(this);
      }
    this->LookupTable = lut;
    if (lut)
      {
      lut->Register(this);
      }
    this->Modified();
    }
}

vtkScalarsToColors *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL )
    {
    this->CreateDefaultLookupTable();
    }
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  this->LookupTable = vtkLookupTable::New();
}

// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->GetInput() )
    {
    this->GetInput()->Update();
    }
}

// Return the method of coloring scalar data.
const char *vtkMapper::GetColorModeAsString(void)
{
  if ( this->ColorMode == VTK_COLOR_MODE_LUMINANCE )
    {
    return "Luminance";
    }
  else if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS )
    {
    return "MapScalars";
    }
  else
    {
    return "Default";
    }
}

// Return the method for obtaining scalar data.
const char *vtkMapper::GetScalarModeAsString(void)
{
  if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    return "UseCellData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    return "UsePointData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    return "UsePointFieldData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    return "UseCellFieldData";
    }
  else
    {
    return "Default";
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkAbstractMapper3D::PrintSelf(os,indent);

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

  os << indent << "Immediate Mode Rendering: "
    << (this->ImmediateModeRendering ? "On\n" : "Off\n");
  os << indent << "Global Immediate Mode Rendering: " <<
    (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n");

  os << indent << "Scalar Visibility: "
    << (this->ScalarVisibility ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";

  os << indent << "UseLookupTableScalarRange: " << this->UseLookupTableScalarRange << "\n";

  os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;

  os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl;

  os << indent << "RenderTime: " << this->RenderTime << endl;

  os << indent << "Resolve Coincident Topology: ";
  if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF )
    {
    os << "Off" << endl;
    }
  else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET )
    {
    os << "Polygon Offset" << endl;
    }
  else
    {
    os << "Shift Z-Buffer" << endl;
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <cmath>
#include <iomanip>
#include <ios>
#include <locale>

#include "vast/logger.hpp"

#include <caf/all.hpp>

#include "vast/concept/printable/std/chrono.hpp"
#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/filesystem.hpp"
#include "vast/error.hpp"

#include "vast/system/accountant.hpp"

#include "vast/detail/coding.hpp"
#include "vast/detail/fill_status_map.hpp"

namespace vast {
namespace system {

namespace {

using accountant_actor = accountant_type::stateful_base<accountant_state>;
constexpr std::chrono::seconds overview_delay(3);

void init(accountant_actor* self, const path& filename) {
  if (!exists(filename.parent())) {
    auto t = mkdir(filename.parent());
    if (!t) {
      VAST_ERROR(self, to_string(t.error()));
      self->quit(t.error());
      return;
    }
  }
  VAST_DEBUG(self, "opens log file:", filename.trim(-4));
  auto& file = self->state.file;
  file.open(filename.str());
  if (!file.is_open()) {
    VAST_ERROR(self, "failed to open file:", filename);
    auto e = make_error(ec::filesystem_error, "failed to open file:", filename);
    self->quit(e);
    return;
  }
  file << "timestamp\thost\tpid\taid\tactor_name\tkey\tvalue\n";
  if (!file)
    self->quit(make_error(ec::filesystem_error));
  VAST_DEBUG(self, "kicks off flush loop");
  self->send(self, flush_atom::value);
#if VAST_LOG_LEVEL >= CAF_LOG_LEVEL_INFO
  self->delayed_send(self, overview_delay, telemetry_atom::value);
#endif
}

template <class T>
void record(accountant_actor* self, const std::string& key, T x,
            time ts = std::chrono::system_clock::now()) {
  using namespace std::chrono;
  auto aid = self->current_sender()->id();
  auto node = self->current_sender()->node();
  auto& st = self->state;
  st.file << to_string(ts) << '\t';
  for (auto byte : node.host_id())
    st.file << static_cast<int>(byte);
  st.file << std::dec << '\t' << node.process_id() << '\t' << aid << '\t'
          << st.actor_map[aid] << '\t' << key << '\t' << std::setprecision(6)
          << x << '\n';
  // Flush after at most 10 seconds.
  if (!st.flush_pending) {
    st.flush_pending = true;
    self->delayed_send(self, 10s, flush_atom::value);
  }
}

void record(accountant_actor* self, const std::string& key, duration x,
            time ts = std::chrono::system_clock::now()) {
  using namespace std::chrono;
  auto us = duration_cast<microseconds>(x).count();
  record(self, key, us, std::move(ts));
}

void record(accountant_actor* self, const std::string& key, time x,
            time ts = std::chrono::system_clock::now()) {
  record(self, key, x.time_since_epoch(), std::move(ts));
}

// Calculate rate in seconds resolution from nanosecond duration.
double calc_rate(const measurement& m) {
  if (m.duration.count() > 0)
    return m.events * 1'000'000'000 / m.duration.count();
  else
    return std::numeric_limits<double>::quiet_NaN();
}

} // namespace <anonymous>

accountant_state::accountant_state(accountant_actor* self) : self{self} {
  // nop
}

void accountant_state::command_line_heartbeat() {
  auto logger = caf::logger::current_logger();
  if (logger && logger->verbosity() >= CAF_LOG_LEVEL_INFO
      && accumulator.node.events > 0) {
    std::ostringstream oss;
    try {
      oss.imbue(std::locale(""));
    } catch (const std::exception& e) {
      VAST_DEBUG(self,
                 "failed to set the locale for statistics output:", e.what());
    }
    auto node_rate = std::round(calc_rate(accumulator.node));
    oss << "ingested " << accumulator.node.events << " events at a rate of "
        << node_rate << " events/sec";
    VAST_INFO_ANON(oss.str());
  }
  accumulator = {};
}

accountant_type::behavior_type accountant(accountant_actor* self,
                                          const path& filename) {
  using namespace std::chrono;
  init(self, filename);
  self->set_exit_handler(
    [=](const caf::exit_msg& msg) {
      self->state.file.flush();
      self->quit(msg.reason);
    }
  );
  self->set_down_handler(
    [=](const caf::down_msg& msg) {
      VAST_DEBUG(self, "received DOWN from", msg.source);
      self->state.actor_map.erase(msg.source.id());
    }
  );
  return {[=](announce_atom, const std::string& name) {
            self->state.actor_map[self->current_sender()->id()] = name;
            self->monitor(self->current_sender());
          },
          [=](const std::string& key, const std::string& value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          // Helpers to avoid to_string(..) in sender context.
          [=](const std::string& key, duration value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, time value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, int64_t value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, uint64_t value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, double value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const report& r) {
            VAST_TRACE(self, "received a report from", self->current_sender());
            time ts = std::chrono::system_clock::now();
            for (const auto& [key, value] : r) {
              auto f = [&, key = key](const auto& x) {
                record(self, key, x, ts);
              };
              caf::visit(f, value);
            }
          },
          [=](const performance_report& r) {
            VAST_TRACE(self, "received a performance report from",
                       self->current_sender());
            time ts = std::chrono::system_clock::now();
            for (const auto& [key, value] : r) {
              record(self, key + ".events", value.events, ts);
              record(self, key + ".duration", value.duration, ts);
              auto rate = calc_rate(value);
              if (std::isfinite(rate))
                record(self, key + ".rate", static_cast<uint64_t>(rate), ts);
              else
                record(self, key + ".rate", "NaN", ts);
#if VAST_LOG_LEVEL >= CAF_LOG_LEVEL_INFO
              auto logger = caf::logger::current_logger();
              if (logger && logger->verbosity() >= CAF_LOG_LEVEL_INFO)
                if (key == "node_throughput")
                  self->state.accumulator.node += value;
#endif
            }
          },
          [=](flush_atom) {
            if (self->state.file)
              self->state.file.flush();
            self->state.flush_pending = false;
          },
          [=](status_atom) {
            using caf::put_dictionary;
            caf::dictionary<caf::config_value> result;
            result.emplace("log-file", filename.str());
            auto& known = put_dictionary(result, "known-actors");
            for (const auto& [aid, name] : self->state.actor_map)
              known.emplace(name, aid);
            detail::fill_status_map(result, self);
            return result;
          },
          [=](telemetry_atom) {
            self->state.command_line_heartbeat();
            self->delayed_send(self, overview_delay, telemetry_atom::value);
          }};
}

} // namespace system
} // namespace vast
<commit_msg>Port VAST to lastet node_id API<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <cmath>
#include <iomanip>
#include <ios>
#include <locale>

#include "vast/logger.hpp"

#include <caf/all.hpp>

#include "vast/concept/printable/std/chrono.hpp"
#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/filesystem.hpp"
#include "vast/error.hpp"

#include "vast/system/accountant.hpp"

#include "vast/detail/coding.hpp"
#include "vast/detail/fill_status_map.hpp"

namespace vast {
namespace system {

namespace {

using accountant_actor = accountant_type::stateful_base<accountant_state>;
constexpr std::chrono::seconds overview_delay(3);

void init(accountant_actor* self, const path& filename) {
  if (!exists(filename.parent())) {
    auto t = mkdir(filename.parent());
    if (!t) {
      VAST_ERROR(self, to_string(t.error()));
      self->quit(t.error());
      return;
    }
  }
  VAST_DEBUG(self, "opens log file:", filename.trim(-4));
  auto& file = self->state.file;
  file.open(filename.str());
  if (!file.is_open()) {
    VAST_ERROR(self, "failed to open file:", filename);
    auto e = make_error(ec::filesystem_error, "failed to open file:", filename);
    self->quit(e);
    return;
  }
  file << "timestamp\tnode\taid\tactor_name\tkey\tvalue\n";
  if (!file)
    self->quit(make_error(ec::filesystem_error));
  VAST_DEBUG(self, "kicks off flush loop");
  self->send(self, flush_atom::value);
#if VAST_LOG_LEVEL >= CAF_LOG_LEVEL_INFO
  self->delayed_send(self, overview_delay, telemetry_atom::value);
#endif
}

template <class T>
void record(accountant_actor* self, const std::string& key, T x,
            time ts = std::chrono::system_clock::now()) {
  using namespace std::chrono;
  auto aid = self->current_sender()->id();
  auto node = self->current_sender()->node();
  auto& st = self->state;
  st.file << to_string(ts) << '\t' << to_string(node) << '\t';
  st.file << std::dec << aid << '\t' << st.actor_map[aid] << '\t' << key << '\t'
          << std::setprecision(6) << x << '\n';
  // Flush after at most 10 seconds.
  if (!st.flush_pending) {
    st.flush_pending = true;
    self->delayed_send(self, 10s, flush_atom::value);
  }
}

void record(accountant_actor* self, const std::string& key, duration x,
            time ts = std::chrono::system_clock::now()) {
  using namespace std::chrono;
  auto us = duration_cast<microseconds>(x).count();
  record(self, key, us, std::move(ts));
}

void record(accountant_actor* self, const std::string& key, time x,
            time ts = std::chrono::system_clock::now()) {
  record(self, key, x.time_since_epoch(), std::move(ts));
}

// Calculate rate in seconds resolution from nanosecond duration.
double calc_rate(const measurement& m) {
  if (m.duration.count() > 0)
    return m.events * 1'000'000'000 / m.duration.count();
  else
    return std::numeric_limits<double>::quiet_NaN();
}

} // namespace <anonymous>

accountant_state::accountant_state(accountant_actor* self) : self{self} {
  // nop
}

void accountant_state::command_line_heartbeat() {
  auto logger = caf::logger::current_logger();
  if (logger && logger->verbosity() >= CAF_LOG_LEVEL_INFO
      && accumulator.node.events > 0) {
    std::ostringstream oss;
    try {
      oss.imbue(std::locale(""));
    } catch (const std::exception& e) {
      VAST_DEBUG(self,
                 "failed to set the locale for statistics output:", e.what());
    }
    auto node_rate = std::round(calc_rate(accumulator.node));
    oss << "ingested " << accumulator.node.events << " events at a rate of "
        << node_rate << " events/sec";
    VAST_INFO_ANON(oss.str());
  }
  accumulator = {};
}

accountant_type::behavior_type accountant(accountant_actor* self,
                                          const path& filename) {
  using namespace std::chrono;
  init(self, filename);
  self->set_exit_handler(
    [=](const caf::exit_msg& msg) {
      self->state.file.flush();
      self->quit(msg.reason);
    }
  );
  self->set_down_handler(
    [=](const caf::down_msg& msg) {
      VAST_DEBUG(self, "received DOWN from", msg.source);
      self->state.actor_map.erase(msg.source.id());
    }
  );
  return {[=](announce_atom, const std::string& name) {
            self->state.actor_map[self->current_sender()->id()] = name;
            self->monitor(self->current_sender());
          },
          [=](const std::string& key, const std::string& value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          // Helpers to avoid to_string(..) in sender context.
          [=](const std::string& key, duration value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, time value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, int64_t value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, uint64_t value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const std::string& key, double value) {
            VAST_TRACE(self, "received", key, "from", self->current_sender());
            record(self, key, value);
          },
          [=](const report& r) {
            VAST_TRACE(self, "received a report from", self->current_sender());
            time ts = std::chrono::system_clock::now();
            for (const auto& [key, value] : r) {
              auto f = [&, key = key](const auto& x) {
                record(self, key, x, ts);
              };
              caf::visit(f, value);
            }
          },
          [=](const performance_report& r) {
            VAST_TRACE(self, "received a performance report from",
                       self->current_sender());
            time ts = std::chrono::system_clock::now();
            for (const auto& [key, value] : r) {
              record(self, key + ".events", value.events, ts);
              record(self, key + ".duration", value.duration, ts);
              auto rate = calc_rate(value);
              if (std::isfinite(rate))
                record(self, key + ".rate", static_cast<uint64_t>(rate), ts);
              else
                record(self, key + ".rate", "NaN", ts);
#if VAST_LOG_LEVEL >= CAF_LOG_LEVEL_INFO
              auto logger = caf::logger::current_logger();
              if (logger && logger->verbosity() >= CAF_LOG_LEVEL_INFO)
                if (key == "node_throughput")
                  self->state.accumulator.node += value;
#endif
            }
          },
          [=](flush_atom) {
            if (self->state.file)
              self->state.file.flush();
            self->state.flush_pending = false;
          },
          [=](status_atom) {
            using caf::put_dictionary;
            caf::dictionary<caf::config_value> result;
            result.emplace("log-file", filename.str());
            auto& known = put_dictionary(result, "known-actors");
            for (const auto& [aid, name] : self->state.actor_map)
              known.emplace(name, aid);
            detail::fill_status_map(result, self);
            return result;
          },
          [=](telemetry_atom) {
            self->state.command_line_heartbeat();
            self->delayed_send(self, overview_delay, telemetry_atom::value);
          }};
}

} // namespace system
} // namespace vast
<|endoftext|>


<commit_before>// $Id: HINFile_test.C,v 1.8 2001/05/06 21:11:13 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////

#include <BALL/FORMAT/HINFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/KERNEL/PTE.h>

///////////////////////////

START_TEST(HINFile, "$Id: HINFile_test.C,v 1.8 2001/05/06 21:11:13 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

HINFile* ptr;

CHECK(HINFile::HINFile())
	ptr = new HINFile;
	TEST_NOT_EQUAL(ptr, 0)
RESULT

CHECK(HINFile::~HINFile())
  delete ptr;
RESULT

HINFile hin;

CHECK(HINFile::HINFile(const String& filename, File::OpenMode open_mode = File::IN))
  hin = HINFile("data/HINFile_test.hin");
  TEST_EQUAL(hin.isValid(), true)
RESULT

System system;
CHECK(HINFile::read(System& system))
  hin.read(system);
	hin.reopen();
	Vector3 position(0.59038, -0.410275, -0.860515);
  TEST_EQUAL(hin.isValid(), true)
  TEST_EQUAL(system.countAtoms(), 648)
  TEST_EQUAL(system.countMolecules(), 216)
	TEST_EQUAL(system.getAtom(0)->getName(), "O")
  TEST_EQUAL(system.getAtom(0)->getElement(), PTE["O"])
	TEST_REAL_EQUAL(system.getAtom(0)->getCharge(), -0.834)
  TEST_EQUAL(system.getAtom(0)->getPosition(), position)
  TEST_NOT_EQUAL(system.getAtom(0)->getRadius(), 0.0)
  TEST_EQUAL(system.getAtom(0)->countBonds(), 2)
RESULT

CHECK(HINFile::write(const System& system))
  String filename;
  NEW_TMP_FILE(filename)
  HINFile hin2(filename, std::ios::out);
	hin2.write(system);
  TEST_FILE("data/HINFile_test2.hin", filename.c_str(), false)
RESULT

CHECK(HINFile::HINFile& operator >> (System& system))
	System system2;
  hin >> system2;
	TEST_EQUAL(system.countAtoms(), system2.countAtoms())
RESULT

CHECK(HINFile::HINFile& operator << (const System& system))
  String filename;
  NEW_TMP_FILE(filename)
  HINFile hin2(filename, std::ios::out);
  hin2 << system;
  TEST_FILE("data/HINFile_test2.hin", filename.c_str(), false)
RESULT

CHECK(HINFile::hasPeriodicBoundary() const )
	TEST_EQUAL(hin.hasPeriodicBoundary(), true)
RESULT

CHECK(HINFile::getPeriodicBoundary() const )
	Box3 box3(-9.35068, -9.35068, -9.35068, 9.35068, 9.35068, 9.35068);
	TEST_EQUAL(hin.getPeriodicBoundary(), box3)
RESULT

CHECK(HINFile::getTemperature() const )
  //BAUSTELLE
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>added: in test for read now testing radius<commit_after>// $Id: HINFile_test.C,v 1.9 2001/05/10 22:16:47 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////

#include <BALL/FORMAT/HINFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/KERNEL/PTE.h>

///////////////////////////

START_TEST(HINFile, "$Id: HINFile_test.C,v 1.9 2001/05/10 22:16:47 amoll Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

HINFile* ptr;

CHECK(HINFile::HINFile())
	ptr = new HINFile;
	TEST_NOT_EQUAL(ptr, 0)
RESULT

CHECK(HINFile::~HINFile())
  delete ptr;
RESULT

HINFile hin;

CHECK(HINFile::HINFile(const String& filename, File::OpenMode open_mode = File::IN))
  hin = HINFile("data/HINFile_test.hin");
  TEST_EQUAL(hin.isValid(), true)
RESULT

System system;
CHECK(HINFile::read(System& system))
  hin.read(system);
	hin.reopen();
	Vector3 position(0.59038, -0.410275, -0.860515);
  TEST_EQUAL(hin.isValid(), true)
  TEST_EQUAL(system.countAtoms(), 648)
  TEST_EQUAL(system.countMolecules(), 216)
	TEST_EQUAL(system.getAtom(0)->getName(), "O")
  TEST_EQUAL(system.getAtom(0)->getElement(), PTE["O"])
	TEST_REAL_EQUAL(system.getAtom(0)->getCharge(), -0.834)
  TEST_EQUAL(system.getAtom(0)->getPosition(), position)
  TEST_REAL_EQUAL(system.getAtom(0)->getRadius(), 1.4)
  TEST_EQUAL(system.getAtom(0)->countBonds(), 2)

  TEST_NOT_EQUAL(system.getAtom(1)->getRadius(), 0)
RESULT

CHECK(HINFile::write(const System& system))
  String filename;
  NEW_TMP_FILE(filename)
  HINFile hin2(filename, std::ios::out);
	hin2.write(system);
  TEST_FILE("data/HINFile_test2.hin", filename.c_str(), false)
RESULT

CHECK(HINFile::HINFile& operator >> (System& system))
	System system2;
  hin >> system2;
	TEST_EQUAL(system.countAtoms(), system2.countAtoms())
RESULT

CHECK(HINFile::HINFile& operator << (const System& system))
  String filename;
  NEW_TMP_FILE(filename)
  HINFile hin2(filename, std::ios::out);
  hin2 << system;
  TEST_FILE("data/HINFile_test2.hin", filename.c_str(), false)
RESULT

CHECK(HINFile::hasPeriodicBoundary() const )
	TEST_EQUAL(hin.hasPeriodicBoundary(), true)
RESULT

CHECK(HINFile::getPeriodicBoundary() const )
	Box3 box3(-9.35068, -9.35068, -9.35068, 9.35068, 9.35068, 9.35068);
	TEST_EQUAL(hin.getPeriodicBoundary(), box3)
RESULT

CHECK(HINFile::getTemperature() const )
  //BAUSTELLE
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>