Exemple #1
0
static void coalesce(Value::Ranges* ranges, const Value::Range& range)
{
  // Note that we assume that ranges has already been coalesced.

  Value::Ranges result;
  Value::Range temp = range;

  for (int i = 0; i < ranges->range_size(); i++) {
    const Value::Range& current = ranges->range(i);

    // Check if current and range overlap. Note, we only need to
    // compare with range and not with temp to check for overlap
    // because we expect ranges to be coalesced to begin with!
    if (current.begin() <= range.end() && current.end() >= range.begin() ) {
      // Update temp with new boundaries.
      temp.set_begin(std::min(range.begin(), current.begin()));
      temp.set_end(std::max(range.end(), current.end()));
    } else { // No overlap.
      result.add_range()->MergeFrom(current);
    }
  }

  result.add_range()->MergeFrom(temp);
  *ranges = result;
}
Exemple #2
0
bool operator == (const Value::Ranges& _left, const Value::Ranges& _right)
{
  Value::Ranges left;
  coalesce(&left, _left);

  Value::Ranges right;
  coalesce(&right, _right);

  if (left.range_size() == right.range_size()) {
    for (int i = 0; i < left.range_size(); i++) {
      // Make sure this range is equal to a range in the right.
      bool found = false;
      for (int j = 0; j < right.range_size(); j++) {
        if (left.range(i).begin() == right.range(j).begin() &&
            left.range(i).end() == right.range(j).end()) {
          found = true;
          break;
        }
      }

      if (!found) {
        return false;
      }
    }

    return true;
  }

  return false;
}
Exemple #3
0
// Coalesce the given un-coalesced 'uranges' into already coalesced 'ranges'.
static void coalesce(Value::Ranges* ranges, const Value::Ranges& uranges)
{
  // Note that we assume that ranges has already been coalesced.

  for (int i = 0; i < uranges.range_size(); i++) {
    coalesce(ranges, uranges.range(i));
  }
}
Exemple #4
0
Value::Ranges operator - (const Value::Ranges& left, const Value::Ranges& right)
{
  Value::Ranges result;

  coalesce(&result, left);
  coalesce(&result, right);

  for (int i = 0; i < right.range_size(); i++) {
    remove(&result, right.range(i));
  }

  return result;
}
Exemple #5
0
bool operator <= (const Value::Ranges& _left, const Value::Ranges& _right)
{
  Value::Ranges left;
  coalesce(&left, _left);

  Value::Ranges right;
  coalesce(&right, _right);

  for (int i = 0; i < left.range_size(); i++) {
    // Make sure this range is a subset of a range in right.
    bool matched = false;
    for (int j = 0; j < right.range_size(); j++) {
      if (left.range(i).begin() >= right.range(j).begin() &&
          left.range(i).end() <= right.range(j).end()) {
        matched = true;
        break;
      }
    }
    if (!matched) {
      return false;
    }
  }

  return true;
}
Exemple #6
0
// Subtract `right_` from `left_`, and return the result as Value::Ranges.
Value::Ranges subtract(const Value::Ranges& left_, const Value::Ranges& right_)
{
  if (left_.range_size() == 0 || right_.range_size() == 0) {
    return left_;
  }

  // Convert the input `Ranges` to `vector<internal::Range>` and
  // sort the vector based on the start of a range.
  auto sortRanges = [](const Value::Ranges& ranges) {
    vector<internal::Range> result;
    result.reserve(ranges.range_size());

    foreach (const Value::Range& range, ranges.range()) {
      result.push_back({range.begin(), range.end()});
    }

    std::sort(
        result.begin(),
        result.end(),
        [](const internal::Range& left, const internal::Range& right) {
          return left.start < right.start;
        });

    return result;
  };

  Value::Ranges result;

  vector<internal::Range> left = sortRanges(left_);
  vector<internal::Range> right = sortRanges(right_);

  vector<internal::Range>::iterator itLeft = left.begin();
  for (vector<internal::Range>::const_iterator itRight = right.cbegin();
       itLeft != left.end() && itRight != right.cend();) {
    // Non-overlap:
    // L: |___|
    // R:       |___|
    if (itLeft->end < itRight->start) {
      Value::Range* newRange = result.add_range();
      newRange->set_begin(itLeft->start);
      newRange->set_end(itLeft->end);

      itLeft++;
      continue;
    }

    // Non-overlap:
    // L:       |___|
    // R: |___|
    if (itLeft->start > itRight->end) {
      itRight++;
      continue;
    }

    if (itLeft->start < itRight->start) {
      Value::Range* newRange = result.add_range();
      newRange->set_begin(itLeft->start);
      newRange->set_end(itRight->start - 1);

      if (itLeft->end <= itRight->end) {
        // L: |_____|
        // R:    |____|
        itLeft++;
      } else {
        // L: |________|
        // R:    |___|
        itLeft->start = itRight->end + 1;
        itRight++;
      }
    } else { // itLeft->start >= itRight->start
      if (itLeft->end <= itRight->end) {
        // L:   |____|
        // R: |________|
        itLeft++;
      } else {
        // L:   |_____|
        // R: |____|
        itLeft->start = itRight->end + 1;
        itRight++;
      }
    }
  }

  // Traverse what's left in the `left`, if any.
  while (itLeft != left.end()) {
    // TODO(mzhu): Consider reserving the exact size.
    Value::Range* newRange = result.add_range();
    newRange->set_begin(itLeft->start);
    newRange->set_end(itLeft->end);

    itLeft++;
  }

  return result;
}