Ejemplo n.º 1
0
TEST(SliceContainerTest, FromUInt8Longer) {
  std::shared_ptr<Builder> builder = BuildValue("[\"the eagle has landed\",\"test\",\"qux\"]");

  uint8_t const* begin = builder->start();
  Slice slice = builder->slice();

  SliceContainer sb(begin, slice.byteSize());
  
  ASSERT_EQ(sb.byteSize(), slice.byteSize());
  ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize()));
  ASSERT_TRUE(sb.slice().isArray());
  ASSERT_NE(sb.data(), begin);
} 
Ejemplo n.º 2
0
TEST(SliceContainerTest, FromSlice) {
  std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\"");

  Slice slice = builder->slice();
  SliceContainer sb(slice);
  
  ASSERT_EQ(sb.byteSize(), slice.byteSize());
  ASSERT_EQ(0, memcmp(sb.data(), slice.begin(), slice.byteSize()));
  ASSERT_EQ(29UL, sb.byteSize());
  ASSERT_TRUE(sb.slice().isString());
  ASSERT_EQ("this is a string of 20 bytes", sb.slice().copyString());
  ASSERT_NE(sb.data(), slice.begin());
} 
Ejemplo n.º 3
0
TEST(SliceContainerTest, FromChar) {
  std::shared_ptr<Builder> builder = BuildValue("null");

  uint8_t const* begin = builder->start();
  Slice slice = builder->slice();

  SliceContainer sb(reinterpret_cast<char const*>(begin), slice.byteSize());
  
  ASSERT_EQ(sb.byteSize(), slice.byteSize());
  ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize()));
  ASSERT_EQ(1UL, sb.byteSize());
  ASSERT_TRUE(sb.slice().isNull());
  ASSERT_NE(sb.data(), begin);
} 
Ejemplo n.º 4
0
TEST(SliceContainerTest, MoveAssign) {
  std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\"");

  Slice slice = builder->slice();
  SliceContainer sb(slice.begin(), slice.byteSize());
  SliceContainer sb2(slice.begin(), slice.byteSize());
  sb2 = std::move(sb);
 
  ASSERT_TRUE(sb.slice().isNone()); // must be empty now 
  ASSERT_EQ(1UL, sb.slice().byteSize());

  ASSERT_EQ(29UL, sb2.byteSize());
  ASSERT_TRUE(sb2.slice().isString());
  ASSERT_EQ("this is a string of 20 bytes", sb2.slice().copyString());

  ASSERT_NE(sb.slice().begin(), sb2.slice().begin());
} 
Ejemplo n.º 5
0
TEST(SliceContainerTest, FromSliceLonger) {
  std::string s("[-1");
  for (size_t i = 0; i < 2000; ++i) {   
    s.push_back(',');
    s.append(std::to_string(i));
  } 
  s.push_back(']');

  std::shared_ptr<Builder> builder = BuildValue(s);

  Slice slice = builder->slice();
  SliceContainer sb(slice);
  
  ASSERT_EQ(sb.byteSize(), slice.byteSize());
  ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize()));
  ASSERT_TRUE(sb.slice().isArray());
  ASSERT_NE(sb.data(), slice.begin());
} 
Ejemplo n.º 6
0
Slice Slice::getFromCompactObject(std::string const& attribute) const {
  ObjectIterator it(*this);
  while (it.valid()) {
    Slice key = it.key();
    if (key.makeKey().isEqualString(attribute)) {
      return Slice(key.start() + key.byteSize());
    }

    it.next();
  }
  // not found
  return Slice();
}
Ejemplo n.º 7
0
TEST(SliceContainerTest, SizeLengthByteSize) {
  std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\"");

  Slice slice = builder->slice();
  SliceContainer sb(slice.begin(), slice.byteSize());
 
  ASSERT_TRUE(sb.slice().isString()); 
  ASSERT_EQ(29UL, sb.size());
  ASSERT_EQ(29UL, sb.length());
  ASSERT_EQ(29UL, sb.byteSize());
  ASSERT_EQ(sb.data(), sb.begin());

  Slice empty;
  sb = SliceContainer(empty);
  
  ASSERT_EQ(1UL, sb.size());
  ASSERT_EQ(1UL, sb.length());
  ASSERT_EQ(1UL, sb.byteSize());
  ASSERT_EQ(sb.data(), sb.begin());
} 
Ejemplo n.º 8
0
// look for the specified attribute inside an Object
// returns a Slice(ValueType::None) if not found
Slice Slice::get(std::string const& attribute) const {
  if (!isObject()) {
    throw Exception(Exception::InvalidValueType, "Expecting Object");
  }

  auto const h = head();
  if (h == 0x0a) {
    // special case, empty object
    return Slice();
  }

  if (h == 0x14) {
    // compact Object
    return getFromCompactObject(attribute);
  }

  ValueLength const offsetSize = indexEntrySize(h);
  ValueLength end = readInteger<ValueLength>(_start + 1, offsetSize);

  // read number of items
  ValueLength n;
  if (offsetSize < 8) {
    n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
  } else {
    n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize);
  }

  if (n == 1) {
    // Just one attribute, there is no index table!
    Slice key = Slice(_start + findDataOffset(h));

    if (key.isString()) {
      if (key.isEqualString(attribute)) {
        return Slice(key.start() + key.byteSize());
      }
      // fall through to returning None Slice below
    } else if (key.isSmallInt() || key.isUInt()) {
      // translate key
      if (Options::Defaults.attributeTranslator == nullptr) {
        throw Exception(Exception::NeedAttributeTranslator);
      }
      if (key.translateUnchecked().isEqualString(attribute)) {
        return Slice(key.start() + key.byteSize());
      }
    }

    // no match or invalid key type
    return Slice();
  }

  ValueLength const ieBase =
      end - n * offsetSize - (offsetSize == 8 ? offsetSize : 0);

  // only use binary search for attributes if we have at least this many entries
  // otherwise we'll always use the linear search
  static ValueLength const SortedSearchEntriesThreshold = 4;

  bool const isSorted = (h >= 0x0b && h <= 0x0e);
  if (isSorted && n >= SortedSearchEntriesThreshold) {
    // This means, we have to handle the special case n == 1 only
    // in the linear search!
    return searchObjectKeyBinary(attribute, ieBase, offsetSize, n);
  }

  return searchObjectKeyLinear(attribute, ieBase, offsetSize, n);
}