This is the new algorithm. Similarly to the legacy format the input is split up into N-1 bytes and a flag byte is used as the Nth byte in the output. - If the previous segment needed any padding the flag is set to the number of bytes used (0..N-2). 0 is possible in the first segment if the input is 0 bytes long. - If no padding was used and there is no more data left in the in
| 182 | - 10 bytes is encoded as X X X X X X X X 9 X X 0 0 0 0 0 0 2 |
| 183 | */ |
| 184 | __attribute__((unused)) static int PackString( |
| 185 | const void *src, // The data to encode |
| 186 | size_t src_len, // The length of the data to encode |
| 187 | void **dst) { // The encoded data |
| 188 | if (src == nullptr) { |
| 189 | return -1; |
| 190 | } |
| 191 | const uchar *usrc = (uchar *)src; // NOLINT |
| 192 | uchar *ptr = (uchar *)*dst; // NOLINT |
| 193 | |
| 194 | for (;;) { |
| 195 | // Figure out how many bytes to copy, copy them and adjust pointers |
| 196 | const size_t copy_len = |
| 197 | std::min((size_t)RDB_ESCAPE_LENGTH - 1, src_len); |
| 198 | memcpy(ptr, usrc, copy_len); |
| 199 | ptr += copy_len; |
| 200 | usrc += copy_len; |
| 201 | src_len -= copy_len; |
| 202 | |
| 203 | // Are we at the end of the input? |
| 204 | if (src_len == 0) { |
| 205 | // pad with zeros if necessary; |
| 206 | const size_t padding_bytes = RDB_ESCAPE_LENGTH - 1 - copy_len; |
| 207 | if (padding_bytes > 0) { |
| 208 | memset(ptr, 0, padding_bytes); |
| 209 | ptr += padding_bytes; |
| 210 | } |
| 211 | // Put the flag byte (0 - N-1) in the output |
| 212 | *(ptr++) = (uchar)copy_len; |
| 213 | break; |
| 214 | } |
| 215 | // We have more data - put the flag byte (N) in and continue |
| 216 | *(ptr++) = RDB_ESCAPE_LENGTH; |
| 217 | } |
| 218 | // *dst = ptr; |
| 219 | return 0; |
| 220 | } |
| 221 | |
| 222 | __attribute__((unused)) static int UnpackInteger(const void *from, |
| 223 | uint32_t length, |