1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to you under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  * https://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.  See the License for the specific language governing
15  * permissions and limitations under the License.
16  */
17 
18 #include <avro/platform.h>
19 #include <stdlib.h>
20 
21 #include "avro/basics.h"
22 #include "avro/io.h"
23 #include "avro/value.h"
24 #include "avro_private.h"
25 #include "encoding.h"
26 
27 
28 /*
29  * Forward declaration; this is basically the same as avro_value_sizeof,
30  * but it doesn't initialize size first.  (Since it will have already
31  * been initialized in avro_value_sizeof itself).
32  */
33 
34 static int
35 sizeof_value(avro_value_t *src, size_t *size);
36 
37 
38 static int
sizeof_array_value(avro_value_t * src,size_t * size)39 sizeof_array_value(avro_value_t *src, size_t *size)
40 {
41 	int  rval;
42 	size_t  element_count;
43 	check(rval, avro_value_get_size(src, &element_count));
44 
45 	if (element_count > 0) {
46 		*size += avro_binary_encoding.size_long(NULL, element_count);
47 
48 		size_t  i;
49 		for (i = 0; i < element_count; i++) {
50 			avro_value_t  child;
51 			check(rval, avro_value_get_by_index(src, i, &child, NULL));
52 			check(rval, sizeof_value(&child, size));
53 		}
54 	}
55 
56 	*size += avro_binary_encoding.size_long(NULL, 0);
57 	return 0;
58 }
59 
60 
61 static int
sizeof_map_value(avro_value_t * src,size_t * size)62 sizeof_map_value(avro_value_t *src, size_t *size)
63 {
64 	int  rval;
65 	size_t  element_count;
66 	check(rval, avro_value_get_size(src, &element_count));
67 
68 	if (element_count > 0) {
69 		*size += avro_binary_encoding.size_long(NULL, element_count);
70 
71 		size_t  i;
72 		for (i = 0; i < element_count; i++) {
73 			avro_value_t  child;
74 			const char  *key;
75 			check(rval, avro_value_get_by_index(src, i, &child, &key));
76 			*size += avro_binary_encoding.size_string(NULL, key);
77 			check(rval, sizeof_value(&child, size));
78 		}
79 	}
80 
81 	*size += avro_binary_encoding.size_long(NULL, 0);
82 	return 0;
83 }
84 
85 static int
sizeof_record_value(avro_value_t * src,size_t * size)86 sizeof_record_value(avro_value_t *src, size_t *size)
87 {
88 	int  rval;
89 	size_t  field_count;
90 	check(rval, avro_value_get_size(src, &field_count));
91 
92 	size_t  i;
93 	for (i = 0; i < field_count; i++) {
94 		avro_value_t  field;
95 		check(rval, avro_value_get_by_index(src, i, &field, NULL));
96 		check(rval, sizeof_value(&field, size));
97 	}
98 
99 	return 0;
100 }
101 
102 static int
sizeof_union_value(avro_value_t * src,size_t * size)103 sizeof_union_value(avro_value_t *src, size_t *size)
104 {
105 	int  rval;
106 	int  discriminant;
107 	avro_value_t  branch;
108 
109 	check(rval, avro_value_get_discriminant(src, &discriminant));
110 	check(rval, avro_value_get_current_branch(src, &branch));
111 	*size += avro_binary_encoding.size_long(NULL, discriminant);
112 	return sizeof_value(&branch, size);
113 }
114 
115 static int
sizeof_value(avro_value_t * src,size_t * size)116 sizeof_value(avro_value_t *src, size_t *size)
117 {
118 	int  rval;
119 
120 	switch (avro_value_get_type(src)) {
121 		case AVRO_BOOLEAN:
122 		{
123 			int  val;
124 			check(rval, avro_value_get_boolean(src, &val));
125 			*size += avro_binary_encoding.size_boolean(NULL, val);
126 			return 0;
127 		}
128 
129 		case AVRO_BYTES:
130 		{
131 			const void  *buf;
132 			size_t  sz;
133 			check(rval, avro_value_get_bytes(src, &buf, &sz));
134 			*size += avro_binary_encoding.size_bytes(NULL, (const char *) buf, sz);
135 			return 0;
136 		}
137 
138 		case AVRO_DOUBLE:
139 		{
140 			double  val;
141 			check(rval, avro_value_get_double(src, &val));
142 			*size += avro_binary_encoding.size_double(NULL, val);
143 			return 0;
144 		}
145 
146 		case AVRO_FLOAT:
147 		{
148 			float  val;
149 			check(rval, avro_value_get_float(src, &val));
150 			*size += avro_binary_encoding.size_float(NULL, val);
151 			return 0;
152 		}
153 
154 		case AVRO_INT32:
155 		{
156 			int32_t  val;
157 			check(rval, avro_value_get_int(src, &val));
158 			*size += avro_binary_encoding.size_long(NULL, val);
159 			return 0;
160 		}
161 
162 		case AVRO_INT64:
163 		{
164 			int64_t  val;
165 			check(rval, avro_value_get_long(src, &val));
166 			*size += avro_binary_encoding.size_long(NULL, val);
167 			return 0;
168 		}
169 
170 		case AVRO_NULL:
171 		{
172 			check(rval, avro_value_get_null(src));
173 			*size += avro_binary_encoding.size_null(NULL);
174 			return 0;
175 		}
176 
177 		case AVRO_STRING:
178 		{
179 			const char  *str;
180 			size_t  sz;
181 			check(rval, avro_value_get_string(src, &str, &sz));
182 			*size += avro_binary_encoding.size_bytes(NULL, str, sz-1);
183 			return 0;
184 		}
185 
186 		case AVRO_ARRAY:
187 			return sizeof_array_value(src, size);
188 
189 		case AVRO_ENUM:
190 		{
191 			int  val;
192 			check(rval, avro_value_get_enum(src, &val));
193 			*size += avro_binary_encoding.size_long(NULL, val);
194 			return 0;
195 		}
196 
197 		case AVRO_FIXED:
198 		{
199 			size_t  sz;
200 			check(rval, avro_value_get_fixed(src, NULL, &sz));
201 			*size += sz;
202 			return 0;
203 		}
204 
205 		case AVRO_MAP:
206 			return sizeof_map_value(src, size);
207 
208 		case AVRO_RECORD:
209 			return sizeof_record_value(src, size);
210 
211 		case AVRO_UNION:
212 			return sizeof_union_value(src, size);
213 
214 		default:
215 		{
216 			avro_set_error("Unknown schema type");
217 			return EINVAL;
218 		}
219 	}
220 
221 	return 0;
222 }
223 
224 int
avro_value_sizeof(avro_value_t * src,size_t * size)225 avro_value_sizeof(avro_value_t *src, size_t *size)
226 {
227 	check_param(EINVAL, size, "size pointer");
228 	*size = 0;
229 	return sizeof_value(src, size);
230 }
231