blob: 2583041ddac0f71c0c7360756a1303c80bb72dff [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include <avro/platform.h>
#include <stdlib.h>
#include "avro/basics.h"
#include "avro/io.h"
#include "avro/value.h"
#include "avro_private.h"
#include "encoding.h"
/*
* Forward declaration; this is basically the same as avro_value_sizeof,
* but it doesn't initialize size first. (Since it will have already
* been initialized in avro_value_sizeof itself).
*/
static int
sizeof_value(avro_value_t *src, size_t *size);
static int
sizeof_array_value(avro_value_t *src, size_t *size)
{
int rval;
size_t element_count;
check(rval, avro_value_get_size(src, &element_count));
if (element_count > 0) {
*size += avro_binary_encoding.size_long(NULL, element_count);
size_t i;
for (i = 0; i < element_count; i++) {
avro_value_t child;
check(rval, avro_value_get_by_index(src, i, &child, NULL));
check(rval, sizeof_value(&child, size));
}
}
*size += avro_binary_encoding.size_long(NULL, 0);
return 0;
}
static int
sizeof_map_value(avro_value_t *src, size_t *size)
{
int rval;
size_t element_count;
check(rval, avro_value_get_size(src, &element_count));
if (element_count > 0) {
*size += avro_binary_encoding.size_long(NULL, element_count);
size_t i;
for (i = 0; i < element_count; i++) {
avro_value_t child;
const char *key;
check(rval, avro_value_get_by_index(src, i, &child, &key));
*size += avro_binary_encoding.size_string(NULL, key);
check(rval, sizeof_value(&child, size));
}
}
*size += avro_binary_encoding.size_long(NULL, 0);
return 0;
}
static int
sizeof_record_value(avro_value_t *src, size_t *size)
{
int rval;
size_t field_count;
check(rval, avro_value_get_size(src, &field_count));
size_t i;
for (i = 0; i < field_count; i++) {
avro_value_t field;
check(rval, avro_value_get_by_index(src, i, &field, NULL));
check(rval, sizeof_value(&field, size));
}
return 0;
}
static int
sizeof_union_value(avro_value_t *src, size_t *size)
{
int rval;
int discriminant;
avro_value_t branch;
check(rval, avro_value_get_discriminant(src, &discriminant));
check(rval, avro_value_get_current_branch(src, &branch));
*size += avro_binary_encoding.size_long(NULL, discriminant);
return sizeof_value(&branch, size);
}
static int
sizeof_value(avro_value_t *src, size_t *size)
{
int rval;
switch (avro_value_get_type(src)) {
case AVRO_BOOLEAN:
{
int val;
check(rval, avro_value_get_boolean(src, &val));
*size += avro_binary_encoding.size_boolean(NULL, val);
return 0;
}
case AVRO_BYTES:
{
const void *buf;
size_t sz;
check(rval, avro_value_get_bytes(src, &buf, &sz));
*size += avro_binary_encoding.size_bytes(NULL, (const char *) buf, sz);
return 0;
}
case AVRO_DOUBLE:
{
double val;
check(rval, avro_value_get_double(src, &val));
*size += avro_binary_encoding.size_double(NULL, val);
return 0;
}
case AVRO_FLOAT:
{
float val;
check(rval, avro_value_get_float(src, &val));
*size += avro_binary_encoding.size_float(NULL, val);
return 0;
}
case AVRO_INT32:
{
int32_t val;
check(rval, avro_value_get_int(src, &val));
*size += avro_binary_encoding.size_long(NULL, val);
return 0;
}
case AVRO_INT64:
{
int64_t val;
check(rval, avro_value_get_long(src, &val));
*size += avro_binary_encoding.size_long(NULL, val);
return 0;
}
case AVRO_NULL:
{
check(rval, avro_value_get_null(src));
*size += avro_binary_encoding.size_null(NULL);
return 0;
}
case AVRO_STRING:
{
const char *str;
size_t sz;
check(rval, avro_value_get_string(src, &str, &sz));
*size += avro_binary_encoding.size_bytes(NULL, str, sz-1);
return 0;
}
case AVRO_ARRAY:
return sizeof_array_value(src, size);
case AVRO_ENUM:
{
int val;
check(rval, avro_value_get_enum(src, &val));
*size += avro_binary_encoding.size_long(NULL, val);
return 0;
}
case AVRO_FIXED:
{
size_t sz;
check(rval, avro_value_get_fixed(src, NULL, &sz));
*size += sz;
return 0;
}
case AVRO_MAP:
return sizeof_map_value(src, size);
case AVRO_RECORD:
return sizeof_record_value(src, size);
case AVRO_UNION:
return sizeof_union_value(src, size);
default:
{
avro_set_error("Unknown schema type");
return EINVAL;
}
}
return 0;
}
int
avro_value_sizeof(avro_value_t *src, size_t *size)
{
check_param(EINVAL, size, "size pointer");
*size = 0;
return sizeof_value(src, size);
}