コード例 #1
0
ファイル: FastXMLVisitor.cpp プロジェクト: DaveInga/mFAST
bool FastXMLVisitor::VisitEnter (const XMLElement & element, const XMLAttribute* /* attr */)
{
  const char* element_name = element.Name();

  if (strcmp(element_name, "templates") == 0 ) {
    instruction_context context;
    context.ns_ = get_optional_attr(element, "templateNs", "");
    context.dictionary_ = get_optional_attr(element, "dictionary", "");

    context_stack_.push_back(context);
    return VisitEnterTemplates(element);
  }

  std::string name_attr = get_optional_attr(element, "name", "");

  if (strcmp(element_name, "templateRef") == 0) {
    return VisitTemplateRef(element, name_attr, num_fields_.back());
  }

  bool result = true;

  if (strcmp(element_name, "template") == 0 ) {
    save_context(element);
    result = VisitEnterTemplate(element, name_attr, num_fields_.back());
  }
  else if (strcmp(element_name, "group") == 0 ) {
    save_context(element);
    result = VisitEnterGroup(element, name_attr, num_fields_.back());
  }
  else if (strcmp(element_name, "sequence") == 0 ) {
    save_context(element);
    result = VisitEnterSequence(element, name_attr, num_fields_.back());
  }
  else if (strcmp(element_name, "define") == 0) {
    return VisitEnterDefine(element, name_attr);
  }
  else {
    int bits;
    bool is_vector;
    if ((strncmp(element_name, "int", 3) == 0 &&  parse_bits(element_name+3, bits, is_vector) ) ||
        (strncmp(element_name, "uInt", 4) == 0 &&  parse_bits(element_name+4, bits, is_vector) )  ) {
      // int8, int16 and uint8, uint16 are not standards, convert them to int32 and uint32 respectively
      if (is_vector)
        return VisitIntVector(element,bits, name_attr, num_fields_.back());
      return VisitInteger(element,bits, name_attr, num_fields_.back());
    }
    else if (strcmp(element_name, "decimal") == 0 ) {
      return VisitDecimal(element, name_attr, num_fields_.back());
    }
    else if (strcmp(element_name, "string") == 0 ) {
      return VisitString(element, name_attr, num_fields_.back());
    }
    else if (strcmp(element_name, "byteVector") == 0 ) {
      return VisitByteVector(element, name_attr, num_fields_.back());
    }
    return true;
  }
  num_fields_.push_back(0);
  return result;
}
コード例 #2
0
ファイル: FastXMLVisitor.cpp プロジェクト: DaveInga/mFAST
void FastXMLVisitor::save_context(const XMLElement & element)
{
  context_stack_.push_back(context_stack_.back());
  instruction_context& context = context_stack_.back();
  context.ns_ = get_optional_attr(element, "ns", context.ns_.c_str());
  context.dictionary_ = get_optional_attr(element, "dictionary", context.dictionary_.c_str());
}
コード例 #3
0
void field_op::parse_field_op(const XMLElement &field_op_element,
                              arena_allocator &alloc) {
  typedef std::map<std::string, operator_enum_t> operator_map_t;
  static const operator_map_t operator_map = map_list_of("none", operator_none)(
      "constant", operator_constant)("delta", operator_delta)(
      "default", operator_default)("copy", operator_copy)(
      "increment", operator_increment)("tail", operator_tail);

  auto itr = operator_map.find(field_op_element.Name());
  if (itr == operator_map.end()) {
    BOOST_THROW_EXCEPTION(
        fast_static_error("S1") << reason_info(
            std::string("Invalid field operator ") + field_op_element.Name()));
  }

  op_ = itr->second;

  const char *opContext_key = get_optional_attr(
      field_op_element, "key", context_ ? context_->key_ : nullptr);
  const char *opContext_dict =
      get_optional_attr(field_op_element, "dictionary",
                        context_ ? context_->dictionary_ : nullptr);
  const char *opContext_ns = get_optional_attr(
      field_op_element, "ns", context_ ? context_->ns_ : nullptr);

  if (opContext_key || opContext_dict || opContext_ns) {
    auto new_context = new (alloc) op_context_t;

    new_context->key_ = string_dup(opContext_key, alloc);
    new_context->ns_ = string_dup(opContext_ns, alloc);
    new_context->dictionary_ = string_dup(opContext_dict, alloc);
    context_ = new_context;
  }
}
コード例 #4
0
field_op::field_op(const decimal_field_instruction *inst,
                   const XMLElement *element, arena_allocator &alloc)
    : op_(inst->field_operator()), context_(inst->op_context()),
      initial_value_(inst->initial_value()), alloc_(&alloc) {
  if (element) {
    const XMLElement *field_op_element = find_field_op_element(*element);
    if (field_op_element) {
      parse_field_op(*field_op_element, alloc);
      const char *init_value_str =
          get_optional_attr(*field_op_element, "value", nullptr);

      if (init_value_str) {
        if (strcmp(element->Name(), "exponent") != 0)
          initial_value_.set(boost::lexical_cast<int64_t>(init_value_str));
        else {
          short exp = 128;
          try {
            exp = boost::lexical_cast<short>(init_value_str);
          } catch (...) {
          }

          if (exp > 63 || exp < -63) {
            BOOST_THROW_EXCEPTION(
                fast_dynamic_error("D11")
                << reason_info(std::string("Invalid exponent initial value: ") +
                               init_value_str));
          }
          initial_value_ =
              decimal_value_storage(0, static_cast<uint16_t>(exp)).storage_;
        }
      }
    }
  }
}
コード例 #5
0
ファイル: FastXMLVisitor.cpp プロジェクト: DaveInga/mFAST
bool FastXMLVisitor::is_mandatory_constant(const XMLElement & element)
{
  if (strcmp("mandatory", get_optional_attr(element, "presence", "mandatory")) == 0 ) {
    if (element.FirstChildElement("constant")) {
      return true;
    }
  }
  return false;
}
コード例 #6
0
ファイル: FastXMLVisitor.cpp プロジェクト: DaveInga/mFAST
bool FastXMLVisitor::VisitExit (const XMLElement & element)
{

  const char* element_name = element.Name();

  bool result = true;

  if (strcmp(element_name, "templates") == 0 ) {
    return VisitExitTemplates(element,num_fields_.back());
  }

  std::string name_attr = get_optional_attr(element, "name", "");

  if (strcmp(element_name, "templateRef") == 0) {
    num_fields_.back() += 1;
  }

  if (name_attr.empty())
    return true;

  typedef bool (FastXMLVisitor::*VisitExitPtr)(const XMLElement &, const std::string&, std::size_t, std::size_t index);
  VisitExitPtr member_ptr;

  if (strcmp(element_name, "template") == 0 ) {
    member_ptr = &FastXMLVisitor::VisitExitTemplate;
  }
  else if (strcmp(element_name, "group") == 0 ) {
    member_ptr = &FastXMLVisitor::VisitExitGroup;
  }
  else if (strcmp(element_name, "sequence") == 0 ) {
    member_ptr = &FastXMLVisitor::VisitExitSequence;
  }
  else if (strcmp(element_name, "define") == 0) {
    return VisitExitDefine(element, name_attr);
  }
  else if (strncmp(element_name, "int",  3) == 0 ||
           strncmp(element_name, "uInt", 4) == 0 ||
           strcmp(element_name, "decimal") == 0  ||
           strcmp(element_name, "string") == 0  ||
           strcmp(element_name, "byteVector") == 0 )
  {
    num_fields_.back() += 1;
    return true;
  }
  else {
    return true;
  }

  std::size_t numFields = num_fields_.back();
  num_fields_.pop_back();
  result = (this->*member_ptr)(element, name_attr, numFields, num_fields_.back());
  num_fields_.back() += 1;
  context_stack_.pop_back();

  return result;
}
コード例 #7
0
aggregate_view_info
view_info_builder::build(const tinyxml2::XMLElement &element,
                         const mfast::group_field_instruction *inst) {
  const char *name = get_optional_attr(element, "name", nullptr);

  if (name == nullptr)
    BOOST_THROW_EXCEPTION(
        fast_static_error("A view must has a name attribute"));

  this->visit(inst, nullptr);
  aggregate_view_info result;
  result.max_depth_ = 0;
  std::size_t sz = std::strlen(name) + 1;
  result.name_ = reinterpret_cast<const char *>(
      std::memcpy(new (alloc_) char[sz], name, sz));

  // result.name_ = std::strcpy(new (alloc_) char[std::strlen(name) + 1],
  //                            name);

  std::deque<field_view_info> fields;

  const tinyxml2::XMLElement *child = element.FirstChildElement();
  while (child != nullptr) {
    if (std::strcmp(child->Name(), "field") == 0) {
      const tinyxml2::XMLElement *grandchild = child->FirstChildElement();
      while (grandchild != nullptr) {
        build_field_view(*grandchild, result.max_depth_, fields);
        grandchild = grandchild->NextSiblingElement();
      }

      fields.back().prop &= ~field_view_info::CONTINUE_BIT;
    }
    child = child->NextSiblingElement();
  }
  field_view_info terminator = {0, nullptr};
  fields.push_back(terminator);

  auto data = new (alloc_) field_view_info[fields.size()];
  std::copy(fields.begin(), fields.end(), data);
  result.data_ = mfast::array_view<const field_view_info>(data, fields.size());
  result.instruction_ = inst;
  return result;
}
コード例 #8
0
void view_info_builder::build_field_view(const tinyxml2::XMLElement &element,
                                         unsigned &max_depth,
                                         std::deque<field_view_info> &fields) {
  std::string ref_name = get_optional_attr(element, "name", "");
  if (ref_name.size()) {
    field_view_info result = {field_view_info::CONTINUE_BIT, nullptr};

    std::vector<int> sequence_indeces;

    std::string ref_name_no_seq_index;
    // remove anything in [] and save the numbers in [] into a queue

    std::size_t pos = 0, new_pos;
    do {
      // find the first occurence of '['
      new_pos = ref_name.find_first_of('[', pos);
      if (new_pos != std::string::npos) {
        ++new_pos;
        ref_name_no_seq_index += ref_name.substr(pos, (new_pos - pos));
        pos = new_pos;
        new_pos = ref_name.find_first_of(']', pos);
        if (new_pos != std::string::npos) {
          try {
            sequence_indeces.push_back(boost::lexical_cast<unsigned>(
                ref_name.substr(pos, new_pos - pos)));
            pos = new_pos;
          } catch (boost::bad_lexical_cast &) {
            BOOST_THROW_EXCEPTION(
                fast_static_error("Invalid reference specification, the token "
                                  "inside [] must be a non-negative integer")
                << reference_name_info(ref_name));
          }
        }
      } else {
        ref_name_no_seq_index += ref_name.substr(pos);
      }
    } while (new_pos != std::string::npos);
    // find the field index
    // std::cout << "finding " << ref_name_no_seq_index << "\n";
    auto it = infos_.find(ref_name_no_seq_index);
    if (it == infos_.end()) {
      BOOST_THROW_EXCEPTION(
          fast_static_error(
              "Invalid reference specification, no such reference name exists")
          << reference_name_info(ref_name));
    }
    const indeces_t &field_indeces = it->second;
    // replace every instance -2 with the indeces in []
    typedef field_view_info::nest_index_t nest_index_t;
    nest_index_t *nest_indices = static_cast<nest_index_t *>(
        alloc_.allocate(sizeof(nest_index_t) * field_indeces.size() + 1));

    unsigned i = 0, j = 0;
    for (i = 0; i < field_indeces.size(); ++i) {
      if (field_indeces[i] != -2)
        nest_indices[i] = field_indeces[i];
      else {
        // -2 is used for specifying undefined sequence index
        if (j < sequence_indeces.size())
          nest_indices[i] = sequence_indeces[j++];
        else {
          BOOST_THROW_EXCEPTION(
              fast_static_error("Invalid reference specification, no such "
                                "reference name exists")
              << reference_name_info(ref_name));
        }
      }
    }
    // the nest_indeces must terminiated with a -1
    nest_indices[i] = -1;
    result.nest_indices = nest_indices;
    max_depth = std::max<unsigned>(max_depth,
                                   static_cast<unsigned>(field_indeces.size()));
    result.prop += 1;
    if (fields.size()) {
      result.prop += std::mismatch(nest_indices, nest_indices + i,
                                   fields.back().nest_indices)
                         .first -
                     nest_indices;
    }
    fields.push_back(result);
  }
}