/*
Copyright 2020 Google LLC
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
/* record.c - methods for different types of records. */
#include "record.h"
#include "system.h"
#include "constants.h"
#include "reftable-error.h"
#include "basics.h"
static struct reftable_record_vtable *
reftable_record_vtable(struct reftable_record *rec);
static void *reftable_record_data(struct reftable_record *rec);
int get_var_int(uint64_t *dest, struct string_view *in)
{
int ptr = 0;
uint64_t val;
if (in->len == 0)
return -1;
val = in->buf[ptr] & 0x7f;
while (in->buf[ptr] & 0x80) {
ptr++;
if (ptr > in->len) {
return -1;
}
val = (val + 1) << 7 | (uint64_t)(in->buf[ptr] & 0x7f);
}
*dest = val;
return ptr + 1;
}
int put_var_int(struct string_view *dest, uint64_t val)
{
uint8_t buf[10] = { 0 };
int i = 9;
int n = 0;
buf[i] = (uint8_t)(val & 0x7f);
i--;
while (1) {
val >>= 7;
if (!val) {
break;
}
val--;
buf[i] = 0x80 | (uint8_t)(val & 0x7f);
i--;
}
n = sizeof(buf) - i - 1;
if (dest->len < n)
return -1;
memcpy(dest->buf, &buf[i + 1], n);
return n;
}
int reftable_is_block_type(uint8_t typ)
{
switch (typ) {
case BLOCK_TYPE_REF:
case BLOCK_TYPE_LOG:
case BLOCK_TYPE_OBJ:
case BLOCK_TYPE_INDEX:
return 1;
}
return 0;
}
uint8_t *reftable_ref_record_val1(const struct reftable_ref_record *rec)
{
switch (rec->value_type) {
case REFTABLE_REF_VAL1:
return rec->value.val1;
case REFTABLE_REF_VAL2:
return rec->value.val2.value;
default:
return NULL;
}
}
uint8_t *reftable_ref_record_val2(const struct reftable_ref_record *rec)
{
switch (rec->value_type) {
case REFTABLE_REF_VAL2:
return rec->value.val2.target_value;
default:
return NULL;
}
}
static int decode_string(struct strbuf *dest, struct string_view in)
{
int start_len = in.len;
uint64_t tsize = 0;
int n = get_var_int(&tsize, &in);
if (n <= 0)
return -1;
string_view_consume(&in, n);
if (in.len < tsize)
return -1;
strbuf_reset(dest);
strbuf_add(dest, in.buf, tsize);
string_view_consume(&in, tsize);
return start_len - in.len;
}
static int encode_string(char *str, struct string_view s)
{
struct string_view start = s;
int l = strlen(str);
int n = put_var_int(&s, l);
if (n < 0)
return -1;
string_view_consume(&s, n);
if (s.len < l)
return -1;
memcpy(s.buf, str, l);
string_view_consume(&s, l);
return start.len - s.len;
}
int reftable_encode_key(int *restart, struct string_view dest,
struct strbuf prev_key, struct strbuf key,
uint8_t extra)
{
struct string_view start = dest;
int prefix_len = common_prefix_size(&prev_key, &key);
uint64_t suffix_len = key.len - prefix_len;
int n = put_var_int(&dest, (uint64_t)prefix_len);
if (n < 0)
return -1;
string_view_consume(&dest, n);
|