in src/storage/rdb/rdb_ziplist.cc [40:122]
StatusOr<std::string> ZipList::Next() {
auto prev_entry_encoded_size = getEncodedLengthSize(pre_entry_len_);
pos_ += prev_entry_encoded_size;
GET_OR_RET(peekOK(1));
auto encoding = static_cast<uint8_t>(input_[pos_]);
if (encoding < ZIP_STR_MASK) {
encoding &= ZIP_STR_MASK;
}
uint32_t len = 0, len_bytes = 0;
std::string value;
if ((encoding) < ZIP_STR_MASK) {
// For integer type, needs to convert to uint8_t* to avoid signed extension
auto data = reinterpret_cast<const uint8_t *>(input_.data());
if ((encoding) == ZIP_STR_06B) {
len_bytes = 1;
len = data[pos_] & 0x3F;
} else if ((encoding) == ZIP_STR_14B) {
GET_OR_RET(peekOK(2));
len_bytes = 2;
len = ((static_cast<uint32_t>(data[pos_]) & 0x3F) << 8) | static_cast<uint32_t>(data[pos_ + 1]);
} else if ((encoding) == ZIP_STR_32B) {
GET_OR_RET(peekOK(5));
len_bytes = 5;
len = (static_cast<uint32_t>(data[pos_ + 1]) << 24) | (static_cast<uint32_t>(data[pos_ + 2]) << 16) |
(static_cast<uint32_t>(data[pos_ + 3]) << 8) | static_cast<uint32_t>(data[pos_ + 4]);
} else {
return {Status::NotOK, "invalid ziplist encoding"};
}
pos_ += len_bytes;
GET_OR_RET(peekOK(len));
value = input_.substr(pos_, len);
pos_ += len;
setPreEntryLen(len_bytes + len + prev_entry_encoded_size);
} else {
GET_OR_RET(peekOK(1));
pos_ += 1 /* the number bytes of length*/;
if ((encoding) == ZIP_INT_8B) {
GET_OR_RET(peekOK(1));
setPreEntryLen(2); // 1byte for encoding and 1byte for the prev entry length
return std::to_string(input_[pos_++]);
} else if ((encoding) == ZIP_INT_16B) {
GET_OR_RET(peekOK(2));
int16_t i16 = 0;
memcpy(&i16, input_.data() + pos_, sizeof(int16_t));
memrev16ifbe(&i16);
setPreEntryLen(3); // 2byte for encoding and 1byte for the prev entry length
pos_ += sizeof(int16_t);
return std::to_string(i16);
} else if ((encoding) == ZIP_INT_24B) {
GET_OR_RET(peekOK(3));
int32_t i32 = 0;
memcpy(reinterpret_cast<uint8_t *>(&i32) + 1, input_.data() + pos_, sizeof(int32_t) - 1);
memrev32ifbe(&i32);
i32 >>= 8;
setPreEntryLen(4); // 3byte for encoding and 1byte for the prev entry length
pos_ += sizeof(int32_t) - 1;
return std::to_string(i32);
} else if ((encoding) == ZIP_INT_32B) {
GET_OR_RET(peekOK(4));
int32_t i32 = 0;
memcpy(&i32, input_.data() + pos_, sizeof(int32_t));
memrev32ifbe(&i32);
setPreEntryLen(5); // 4byte for encoding and 1byte for the prev entry length
pos_ += sizeof(int32_t);
return std::to_string(i32);
} else if ((encoding) == ZIP_INT_64B) {
GET_OR_RET(peekOK(8));
int64_t i64 = 0;
memcpy(&i64, input_.data() + pos_, sizeof(int64_t));
memrev64ifbe(&i64);
setPreEntryLen(9); // 8byte for encoding and 1byte for the prev entry length
pos_ += sizeof(int64_t);
return std::to_string(i64);
} else if (encoding >= ZIP_INT_IMM_MIN && encoding <= ZIP_INT_IMM_MAX) {
setPreEntryLen(1); // 8byte for encoding and 1byte for the prev entry length
return std::to_string((encoding & 0x0F) - 1);
} else {
return {Status::NotOK, "invalid ziplist encoding"};
}
}
return value;
}