コード例 #1
0
ファイル: binary.cpp プロジェクト: Flusspferd/flusspferd
array binary::split(value delim, object options) {
  local_root_scope scope;
  std::vector<binary*> delims;

  // Parse the delimiter into the vector of delims.
  if (delim.is_int()) { // single Number
    if (delim.get_int() < 0 || delim.get_int() > 255)
      throw exception("Outside byte range", "RangeError");
    element_type e = delim.get_int();
    delims.push_back(&create(&e, 1));
  } else if (delim.is_object()) {
    object obj = delim.get_object();

    if (obj.is_array()) { // Array
      array arr(obj);
      std::size_t n = arr.length();

      for (std::size_t i = 0; i < n; ++i) {
        binary &new_delim =
          flusspferd::create<byte_string>(
            fusion::vector2<element_type*, std::size_t>(0, 0));
        arguments arg;
        arg.push_back(arr.get_element(i));
        new_delim.do_append(arg);
        if (new_delim.get_length() > 0)
          delims.push_back(&new_delim);
      }
    } else { // Binary
      binary &b = flusspferd::get_native<binary>(obj);
      if (b.get_length() > 0)
        delims.push_back(&b);
    }
  }

  if (delims.empty())
    throw exception("Need at least one valid delimiter");

  // Options
  std::size_t count = std::numeric_limits<std::size_t>::max();
  bool include_delimiter = false;

  // (only search options if the options object is not null)
  if (!options.is_null()) {
    // "count" option
    value count_ = options.get_property("count");
    if (!count_.is_undefined_or_null())
      count = count_.to_number();

    // "includeDelimiter" option
    value include_delimiter_ = options.get_property("includeDelimiter");
    if (!include_delimiter_.is_undefined_or_null())
      include_delimiter = include_delimiter_.to_boolean();
  }

  // Main loop

  typedef vector_type::iterator iterator;
  iterator pos = v_data.begin();

  array results = flusspferd::create<array>();

  // Loop only through the first count-1 elements
  for (std::size_t n = 1; n < count; ++n) {
    // Search for the first occurring delimiter
    std::size_t delim_id = delims.size();
    iterator first_found = v_data.end();
    for (std::size_t i = 0; i < delims.size(); ++i) {
      binary &delim = *delims[i];
      iterator found = std::search(
        pos, v_data.end(),
        delim.get_data().begin(), delim.get_data().end());
      if (found < first_found) {
        first_found = found;
        delim_id = i;
      }
    }

    // No delimiter found
    if (delim_id == delims.size())
      break;

    binary &elem = create_range(pos, first_found);

    // Add element
    results.push(elem);

    // Possible add delimiter
    if (include_delimiter)
      results.push(*delims[delim_id]);

    // Advance position _after_ the delimiter.
    pos = first_found + delims[delim_id]->get_length();
  }

  // Add last element, possibly containing delimiters
  results.push(create_range(pos, v_data.end()));

  return results;
}