static int TraditionalGenerate (TRI_key_generator_t* const generator, const size_t maxLength, const TRI_voc_tick_t tick, const char* const userKey, char* const outBuffer, size_t* const outLength, bool isRestore) { traditional_keygen_t* data; char* current; data = (traditional_keygen_t*) generator->_data; assert(data != NULL); current = outBuffer; if (userKey != NULL) { size_t userKeyLength; // user has specified a key if (! data->_allowUserKeys && ! isRestore) { // we do not allow user-generated keys return TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED; } userKeyLength = strlen(userKey); if (userKeyLength > maxLength) { // user key is too long return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } else if (userKeyLength == 0) { // user key is empty return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } // validate user-supplied key if (! ValidateKey(userKey)) { return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } memcpy(outBuffer, userKey, userKeyLength); current += userKeyLength; } else { // user has not specified a key, generate one based on tick current += TRI_StringUInt64InPlace(tick, outBuffer); } // add 0 byte *current = '\0'; if (current - outBuffer > (int) maxLength) { return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } *outLength = (current - outBuffer); return TRI_ERROR_NO_ERROR; }
int TRI_AppendUInt64StringBuffer (TRI_string_buffer_t * self, uint64_t attr) { int res; size_t len; res = Reserve(self, 21); if (res != TRI_ERROR_NO_ERROR) { return res; } len = TRI_StringUInt64InPlace(attr, self->_current); self->_current += len; return TRI_ERROR_NO_ERROR; }
static int AutoIncrementGenerate (TRI_key_generator_t* const generator, const size_t maxLength, const TRI_voc_tick_t tick, const char* const userKey, char* const outBuffer, size_t* const outLength, bool isRestore) { autoincrement_keygen_t* data; char* current; data = (autoincrement_keygen_t*) generator->_data; assert(data != NULL); current = outBuffer; if (userKey != NULL) { uint64_t userKeyValue; size_t userKeyLength; // user has specified a key if (! data->_allowUserKeys && ! isRestore) { // we do not allow user-generated keys return TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED; } userKeyLength = strlen(userKey); if (userKeyLength > maxLength) { // user key is too long return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } // validate user-supplied key if (! ValidateNumericKey(userKey)) { return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } memcpy(outBuffer, userKey, userKeyLength); current += userKeyLength; userKeyValue = TRI_UInt64String2(userKey, userKeyLength); if (userKeyValue > data->_lastValue) { // update our last value data->_lastValue = userKeyValue; } } else { // user has not specified a key, generate one based on algorithm uint64_t keyValue = AutoIncrementNext(data->_lastValue, data->_increment, data->_offset); // bounds and sanity checks if (keyValue == UINT64_MAX || keyValue < data->_lastValue) { return TRI_ERROR_ARANGO_OUT_OF_KEYS; } assert(keyValue > data->_lastValue); // update our last value data->_lastValue = keyValue; current += TRI_StringUInt64InPlace(keyValue, outBuffer); } // add 0 byte *current = '\0'; if (current - outBuffer > (int) maxLength) { return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD; } *outLength = (current - outBuffer); return TRI_ERROR_NO_ERROR; }
void DocumentAccessor::lookupDocumentAttribute (char const* name, size_t nameLength) { if (*name == '_' && name[1] != '\0') { if (name[1] == 'k' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_KEY, nameLength) == 0) { // _key value is copied into JSON char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); if (key == nullptr) { setToNull(); return; } _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, key, strlen(key))); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } if (name[1] == 'i' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_ID, nameLength) == 0) { // _id char buffer[512]; // big enough for max key length + max collection name length size_t pos = _resolver->getCollectionName(&buffer[0], _document->_info._cid); buffer[pos++] = '/'; char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); if (key == nullptr) { setToNull(); return; } size_t len = strlen(key); memcpy(&buffer[pos], key, len); buffer[pos + len] = '\0'; _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len)); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } if (name[1] == 'r' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_REV, nameLength) == 0) { // _rev char buffer[21]; TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_mptr); size_t len = TRI_StringUInt64InPlace(rid, &buffer[0]); _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], len)); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } if (TRI_IS_EDGE_MARKER(_mptr)) { if (name[1] == 'f' && nameLength == 5 && memcmp(name, TRI_VOC_ATTRIBUTE_FROM, nameLength) == 0) { // _from char buffer[512]; // big enough for max key length + max collection name length size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_FROM_CID(_mptr)); buffer[pos++] = '/'; char const* key = TRI_EXTRACT_MARKER_FROM_KEY(_mptr); if (key == nullptr) { setToNull(); return; } size_t len = strlen(key); memcpy(&buffer[pos], key, len); buffer[pos + len] = '\0'; _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len)); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } if (name[1] == 't' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_TO, nameLength) == 0) { // to char buffer[512]; // big enough for max key length + max collection name length size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_TO_CID(_mptr)); buffer[pos++] = '/'; char const* key = TRI_EXTRACT_MARKER_TO_KEY(_mptr); if (key == nullptr) { setToNull(); return; } size_t len = strlen(key); memcpy(&buffer[pos], key, len); buffer[pos + len] = '\0'; _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len)); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } } // fall-through intentional } auto shaper = _document->getShaper(); TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name); if (pid == 0) { // attribute does not exist setToNull(); return; } // attribute exists TRI_shaped_json_t document; TRI_EXTRACT_SHAPED_JSON_MARKER(document, _mptr->getDataPtr()); TRI_shaped_json_t json; TRI_shape_t const* shape; bool ok = shaper->extractShapedJson(&document, 0, pid, &json, &shape); if (ok && shape != nullptr) { _json.reset(TRI_JsonShapedJson(shaper, &json)); if (_json.get() == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _current = _json.get(); return; } // not found setToNull(); }