const char* IndexMetaDataKey::decode(const char* start, const char* limit, IndexMetaDataKey* result) { KeyPrefix prefix; const char* p = KeyPrefix::decode(start, limit, &prefix); if (!p) return 0; ASSERT(prefix.m_databaseId); ASSERT(!prefix.m_objectStoreId); ASSERT(!prefix.m_indexId); if (p == limit) return 0; unsigned char typeByte = 0; p = decodeByte(p, limit, typeByte); ASSERT_UNUSED(typeByte, typeByte == IndexMetaDataTypeByte); if (p == limit) return 0; p = decodeVarInt(p, limit, result->m_objectStoreId); if (!p) return 0; p = decodeVarInt(p, limit, result->m_indexId); if (!p) return 0; if (p == limit) return 0; return decodeByte(p, limit, result->m_metaDataType); }
int compareEncodedStringsWithLength(const char*& p, const char* limitP, const char*& q, const char* limitQ) { ASSERT(&p != &q); ASSERT(limitP >= p); ASSERT(limitQ >= q); int64_t lenP, lenQ; p = decodeVarInt(p, limitP, lenP); q = decodeVarInt(q, limitQ, lenQ); ASSERT(p && q); ASSERT(lenP >= 0); ASSERT(lenQ >= 0); ASSERT(p + lenP * 2 <= limitP); ASSERT(q + lenQ * 2 <= limitQ); const char* startP = p; const char* startQ = q; p += lenP * 2; q += lenQ * 2; if (p > limitP || q > limitQ) return 0; const size_t lmin = static_cast<size_t>(lenP < lenQ ? lenP : lenQ); if (int x = memcmp(startP, startQ, lmin * 2)) return x; if (lenP == lenQ) return 0; return (lenP > lenQ) ? 1 : -1; }
int compareEncodedIDBKeys(const char*& p, const char* limitA, const char*& q, const char* limitB) { ASSERT(&p != &q); ASSERT(p < limitA); ASSERT(q < limitB); unsigned char typeA = *p++; unsigned char typeB = *q++; if (int x = IDBKey::compareTypes(keyTypeByteToKeyType(typeA), keyTypeByteToKeyType(typeB))) return x; switch (typeA) { case kIDBKeyNullTypeByte: case kIDBKeyMinKeyTypeByte: // Null type or max type; no payload to compare. return 0; case kIDBKeyArrayTypeByte: { int64_t lengthA, lengthB; p = decodeVarInt(p, limitA, lengthA); if (!p) return 0; q = decodeVarInt(q, limitB, lengthB); if (!q) return 0; if (lengthA < 0 || lengthB < 0) return 0; for (int64_t i = 0; i < lengthA && i < lengthB; ++i) { if (int cmp = compareEncodedIDBKeys(p, limitA, q, limitB)) return cmp; } if (lengthA < lengthB) return -1; if (lengthA > lengthB) return 1; return 0; } case kIDBKeyStringTypeByte: return compareEncodedStringsWithLength(p, limitA, q, limitB); case kIDBKeyDateTypeByte: case kIDBKeyNumberTypeByte: { double d, e; p = decodeDouble(p, limitA, &d); ASSERT(p); q = decodeDouble(q, limitB, &e); ASSERT(q); if (d < e) return -1; if (d > e) return 1; return 0; } } ASSERT_NOT_REACHED(); return 0; }
const char* extractEncodedIDBKey(const char* start, const char* limit, Vector<char>* result) { ASSERT(result); const char* p = start; if (p >= limit) return 0; unsigned char type = *p++; switch (type) { case kIDBKeyNullTypeByte: case kIDBKeyMinKeyTypeByte: *result = encodeByte(type); return p; case kIDBKeyArrayTypeByte: { int64_t length; p = decodeVarInt(p, limit, length); if (!p) return 0; if (length < 0) return 0; result->clear(); result->append(start, p - start); while (length--) { Vector<char> subkey; p = extractEncodedIDBKey(p, limit, &subkey); if (!p) return 0; result->append(subkey); } return p; } case kIDBKeyStringTypeByte: { int64_t length; p = decodeVarInt(p, limit, length); if (!p) return 0; if (p + length * 2 > limit) return 0; result->clear(); result->append(start, p - start + length * 2); return p + length * 2; } case kIDBKeyDateTypeByte: case kIDBKeyNumberTypeByte: if (p + sizeof(double) > limit) return 0; result->clear(); result->append(start, 1 + sizeof(double)); return p + sizeof(double); } ASSERT_NOT_REACHED(); return 0; }
void ProtoDeserializerVisitor::read(const uint32_t &id, unsigned char &v) { m_size -= readAndValidateKey(id, ProtoSerializerVisitor::VARINT); uint64_t _v = 0; m_size -= decodeVarInt(m_buffer, _v); v = static_cast<unsigned char>(_v); }
void ProtoDeserializerVisitor::read(const uint32_t &id, uint64_t &v) { m_size -= readAndValidateKey(id, ProtoSerializerVisitor::VARINT); uint64_t _v = 0; m_size -= decodeVarInt(m_buffer, _v); v = _v; }
void ProtoDeserializerVisitor::read(const uint32_t &fourByteID, const uint8_t &oneByteID, const string &/*longName*/, const string &/*shortName*/, uint64_t &v) { m_size -= readAndValidateKey( (oneByteID > 0 ? oneByteID : fourByteID) , ProtoSerializerVisitor::VARINT); uint64_t _v = 0; m_size -= decodeVarInt(m_buffer, _v); v = _v; }
FullContainerKey::FullContainerKey(const KeyConstraint &constraint, const void *data) : constraint_(constraint), body_(NULL), size_(0) { try { if (data == NULL) { GS_THROW_USER_ERROR(GS_ERROR_DS_DS_CONTAINER_NAME_INVALID, "container/table name is empty"); } ContainerKeyInStream in(util::ArrayInStream(data, sizeof(uint32_t))); if (ValueProcessor::varSizeIs1Byte(static_cast<const uint8_t*>(data)[0]) || ValueProcessor::varSizeIs4Byte(static_cast<const uint8_t*>(data)[0])) { size_ = static_cast<size_t>(decodeVarInt(in)); } else { GS_THROW_USER_ERROR(GS_ERROR_DS_DS_CONTAINER_NAME_INVALID, "failed to decode container/table name size"); } body_ = static_cast<const uint8_t*>(data) + in.base().position(); } catch (std::exception &e) { GS_RETHROW_USER_ERROR(e, GS_EXCEPTION_MERGE_MESSAGE(e, "failed to construct container/table name")); } }
const char* IndexDataKey::decode(const char* start, const char* limit, IndexDataKey* result) { KeyPrefix prefix; const char* p = KeyPrefix::decode(start, limit, &prefix); if (!p) return 0; ASSERT(prefix.m_databaseId); ASSERT(prefix.m_objectStoreId); ASSERT(prefix.m_indexId >= MinimumIndexId); result->m_databaseId = prefix.m_databaseId; result->m_objectStoreId = prefix.m_objectStoreId; result->m_indexId = prefix.m_indexId; result->m_sequenceNumber = -1; result->m_encodedPrimaryKey = minIDBKey(); p = extractEncodedIDBKey(p, limit, &result->m_encodedUserKey); if (!p) return 0; // [optional] sequence number if (p == limit) return p; p = decodeVarInt(p, limit, result->m_sequenceNumber); if (!p) return 0; // [optional] primary key if (p == limit) return p; p = extractEncodedIDBKey(p, limit, &result->m_encodedPrimaryKey); if (!p) return 0; return p; }
const char* decodeIDBKey(const char* p, const char* limit, RefPtr<IDBKey>& foundKey) { ASSERT(limit >= p); if (p >= limit) return 0; unsigned char type = *p++; switch (type) { case IDBKeyNullTypeByte: foundKey = IDBKey::createInvalid(); return p; case IDBKeyArrayTypeByte: { int64_t length; p = decodeVarInt(p, limit, length); if (!p) return 0; if (length < 0) return 0; IDBKey::KeyArray array; while (length--) { RefPtr<IDBKey> key; p = decodeIDBKey(p, limit, key); if (!p) return 0; array.append(key); } foundKey = IDBKey::createArray(array); return p; } case IDBKeyStringTypeByte: { String s; p = decodeStringWithLength(p, limit, s); if (!p) return 0; foundKey = IDBKey::createString(s); return p; } case IDBKeyDateTypeByte: { double d; p = decodeDouble(p, limit, &d); if (!p) return 0; foundKey = IDBKey::createDate(d); return p; } case IDBKeyNumberTypeByte: { double d; p = decodeDouble(p, limit, &d); if (!p) return 0; foundKey = IDBKey::createNumber(d); return p; } } ASSERT_NOT_REACHED(); return 0; }
const char* decodeStringWithLength(const char* p, const char* limit, String& foundString) { ASSERT(limit >= p); int64_t len; p = decodeVarInt(p, limit, len); if (!p) return 0; if (p + len * 2 > limit) return 0; foundString = decodeString(p, p + len * 2); p += len * 2; return p; }
uint32_t ProtoDeserializerVisitor::readAndValidateKey(const uint32_t &id, const ProtoSerializerVisitor::PROTOBUF_TYPE &expectedType) { uint64_t key = 0; const uint32_t size = decodeVarInt(m_buffer, key); const uint32_t fieldId = static_cast<uint32_t>(key >> 3); const ProtoSerializerVisitor::PROTOBUF_TYPE protoType = static_cast<ProtoSerializerVisitor::PROTOBUF_TYPE>(key & 0x7); if (fieldId != id) { clog << "[core::base::ProtoDeserializerVisitor]: ERROR! Field ids do not match: Found " << fieldId << ", expected: " << id << endl; } if (protoType != expectedType) { clog << "[core::base::ProtoDeserializerVisitor]: ERROR! Expected type does not match: Found " << protoType << ", expected " << expectedType << endl; } return size; }
const char* DatabaseFreeListKey::decode(const char* start, const char* limit, DatabaseFreeListKey* result) { KeyPrefix prefix; const char *p = KeyPrefix::decode(start, limit, &prefix); if (!p) return 0; ASSERT(!prefix.m_databaseId); ASSERT(!prefix.m_objectStoreId); ASSERT(!prefix.m_indexId); if (p == limit) return 0; unsigned char typeByte = *p++; ASSERT_UNUSED(typeByte, typeByte == kDatabaseFreeListTypeByte); if (p == limit) return 0; return decodeVarInt(p, limit, result->m_databaseId); }
void ProtoDeserializerVisitor::read(const uint32_t &fourByteID, const uint8_t &oneByteID, const string &/*longName*/, const string &/*shortName*/, void *data, const uint32_t &size) { m_size -= readAndValidateKey( (oneByteID > 0 ? oneByteID : fourByteID) , ProtoSerializerVisitor::LENGTH_DELIMITED); // Read length. uint64_t length = 0; m_size -= decodeVarInt(m_buffer, length); // Read data. char *_data = new char[length]; m_buffer.read(_data, length); m_size -= length; // Move data. memset(data, 0, size); memcpy(data, _data, (size < length ? size : length)); OPENDAVINCI_CORE_DELETE_ARRAY(_data); }
void ProtoDeserializerVisitor::read(const uint32_t &fourByteID, const uint8_t &oneByteID, const string &/*longName*/, const string &/*shortName*/, string &v) { m_size -= readAndValidateKey( (oneByteID > 0 ? oneByteID : fourByteID) , ProtoSerializerVisitor::LENGTH_DELIMITED); // Read length. uint64_t length = 0; m_size -= decodeVarInt(m_buffer, length); // Read string. char *str = new char[length+1]; m_buffer.read(str, length); m_size -= length; // Create string. str[length] = 0; v = string(str, length); OPENDAVINCI_CORE_DELETE_ARRAY(str); }
void ProtoDeserializerVisitor::read(const uint32_t &id, void *data, const uint32_t &size) { m_size -= readAndValidateKey(id, ProtoSerializerVisitor::LENGTH_DELIMITED); // Read length. uint64_t length = 0; m_size -= decodeVarInt(m_buffer, length); // Read data. char *_data = new char[length]; m_buffer.read(_data, length); m_size -= length; // Move data. memset(data, 0, size); memcpy(data, _data, (size < length ? size : length)); OPENDAVINCI_CORE_DELETE_ARRAY(_data); }
void ProtoDeserializerVisitor::read(const uint32_t &id, string &v) { m_size -= readAndValidateKey(id, ProtoSerializerVisitor::LENGTH_DELIMITED); // Read length. uint64_t length = 0; m_size -= decodeVarInt(m_buffer, length); // Read string. char *str = new char[length+1]; m_buffer.read(str, length); m_size -= length; // Create string. str[length] = 0; v = string(str, length); OPENDAVINCI_CORE_DELETE_ARRAY(str); }
// FIXME: We never use this to look up index ids, because a mapping // is kept at a higher level. const char* IndexNamesKey::decode(const char* start, const char* limit, IndexNamesKey* result) { KeyPrefix prefix; const char* p = KeyPrefix::decode(start, limit, &prefix); if (!p) return 0; ASSERT(prefix.m_databaseId); ASSERT(!prefix.m_objectStoreId); ASSERT(!prefix.m_indexId); if (p == limit) return 0; unsigned char typeByte = *p++; ASSERT_UNUSED(typeByte, typeByte == kIndexNamesKeyTypeByte); if (p == limit) return 0; p = decodeVarInt(p, limit, result->m_objectStoreId); if (!p) return 0; return decodeStringWithLength(p, limit, result->m_indexName); }
IDBKeyPath decodeIDBKeyPath(const char* p, const char* limit) { // May be typed, or may be a raw string. An invalid leading // byte sequence is used to identify typed coding. New records are // always written as typed. if (p == limit || (limit - p >= 2 && (*p != IDBKeyPathTypeCodedByte1 || *(p + 1) != IDBKeyPathTypeCodedByte2))) return IDBKeyPath(decodeString(p, limit)); p += 2; ASSERT(p != limit); IDBKeyPath::Type type = static_cast<IDBKeyPath::Type>(*p++); switch (type) { case IDBKeyPath::NullType: ASSERT(p == limit); return IDBKeyPath(); case IDBKeyPath::StringType: { String string; p = decodeStringWithLength(p, limit, string); ASSERT(p == limit); return IDBKeyPath(string); } case IDBKeyPath::ArrayType: { Vector<String> array; int64_t count; p = decodeVarInt(p, limit, count); ASSERT(p); ASSERT(count >= 0); while (count--) { String string; p = decodeStringWithLength(p, limit, string); ASSERT(p); array.append(string); } ASSERT(p == limit); return IDBKeyPath(array); } } ASSERT_NOT_REACHED(); return IDBKeyPath(); }
void FullContainerKey::deserialize(util::StackAllocator &alloc, FullContainerKeyComponents &components, BitArray &upperCaseBit, bool unNormalized) const { try { if (isEmpty()) { GS_THROW_USER_ERROR(GS_ERROR_DS_DS_CONTAINER_NAME_INVALID, "container/table name is empty"); } components.clear(); upperCaseBit.clear(); ContainerKeyInStream in(util::ArrayInStream(body_, size_)); const char8_t *normalizedStr[3] = { NULL, NULL, NULL }; uint8_t flag; in >> flag; if (flag & DBID_EXISTS) { in >> components.dbId_; } else { components.dbId_ = GS_PUBLIC_DB_ID; } components.baseNameSize_ = decodeVarInt(in); normalizedStr[0] = reinterpret_cast<const char8_t*>(body_ + in.base().position()); in.base().position(in.base().position() + components.baseNameSize_); if (flag & LARGE_CONTAINERID_EXISTS) { components.largeContainerId_ = decodeVarLong(in); } if (flag & NODE_AFFINITY_NUM) { components.affinityNumber_ = decodeVarLong(in); } else if (flag & NODE_AFFINITY_STR) { components.affinityStringSize_ = decodeVarInt(in); normalizedStr[1] = reinterpret_cast<const char8_t*>(body_ + in.base().position()); in.base().position(in.base().position() + components.affinityStringSize_); } if (flag & SYSTEM_PART_ID_NUM) { components.systemPartId_ = decodeVarLong(in); } else if (flag & SYSTEM_PART_ID_STR) { components.systemPartSize_ = decodeVarInt(in); normalizedStr[2] = reinterpret_cast<const char8_t*>(body_ + in.base().position()); in.base().position(in.base().position() + components.systemPartSize_); } const uint64_t strLength = components.baseNameSize_ + components.affinityStringSize_ + components.systemPartSize_; if (in.base().remaining() != strLengthToBitLength(strLength)) { GS_THROW_USER_ERROR(GS_ERROR_DS_DS_CONTAINER_NAME_INVALID, "size of container/table name is invalid"); } else { upperCaseBit.reserve(strLength); upperCaseBit.putAll(body_ + in.base().position(), strLength); in.base().position(in.base().position() + in.base().remaining()); } if (in.base().position() != size_) { GS_THROW_USER_ERROR(GS_ERROR_DS_DS_CONTAINER_NAME_INVALID, "size of container/table name is invalid"); } if (unNormalized) { util::XArray<char8_t> buf(alloc); buf.resize(static_cast<size_t>(strLength), '\0'); uint64_t startPos = 0; createOriginalString(normalizedStr[0], components.baseNameSize_, buf.data()+startPos, upperCaseBit, startPos); components.baseName_ = buf.data()+startPos; startPos += components.baseNameSize_; if (components.affinityStringSize_ > 0) { createOriginalString(normalizedStr[1], components.affinityStringSize_, buf.data()+startPos, upperCaseBit, startPos); components.affinityString_ = buf.data()+startPos; startPos += components.affinityStringSize_; } if (components.systemPartSize_ > 0) { createOriginalString(normalizedStr[2], components.systemPartSize_, buf.data()+startPos, upperCaseBit, startPos); components.systemPart_ = buf.data()+startPos; startPos += components.systemPartSize_; } } else { components.baseName_ = normalizedStr[0]; if (components.affinityStringSize_ > 0) { components.affinityString_ = normalizedStr[1]; } if (components.systemPartSize_ > 0) { components.systemPart_ = normalizedStr[2]; } } }