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_private.h"
19 #include <string.h>
20 #include "datum.h"
21
22 static int
array_equal(struct avro_array_datum_t * a,struct avro_array_datum_t * b)23 array_equal(struct avro_array_datum_t *a, struct avro_array_datum_t *b)
24 {
25 if (!avro_schema_equal(a->schema, b->schema)) {
26 return 0;
27 }
28
29 long i;
30
31 if (a->els->num_entries != b->els->num_entries) {
32 return 0;
33 }
34 for (i = 0; i < a->els->num_entries; i++) {
35 union {
36 st_data_t data;
37 avro_datum_t datum;
38 } ael, bel;
39 st_lookup(a->els, i, &ael.data);
40 st_lookup(b->els, i, &bel.data);
41 if (!avro_datum_equal(ael.datum, bel.datum)) {
42 return 0;
43 }
44 }
45 return 1;
46 }
47
48 struct st_equal_args {
49 int rval;
50 st_table *st;
51 };
52
53 static int
st_equal_foreach(char * key,avro_datum_t datum,struct st_equal_args * args)54 st_equal_foreach(char *key, avro_datum_t datum, struct st_equal_args *args)
55 {
56 union {
57 avro_datum_t datum_other;
58 st_data_t data;
59 } val;
60 if (!st_lookup(args->st, (st_data_t) key, &(val.data))) {
61 args->rval = 0;
62 return ST_STOP;
63 }
64 if (!avro_datum_equal(datum, val.datum_other)) {
65 args->rval = 0;
66 return ST_STOP;
67 }
68 return ST_CONTINUE;
69 }
70
map_equal(struct avro_map_datum_t * a,struct avro_map_datum_t * b)71 static int map_equal(struct avro_map_datum_t *a, struct avro_map_datum_t *b)
72 {
73 if (!avro_schema_equal(a->schema, b->schema)) {
74 return 0;
75 }
76
77 struct st_equal_args args = { 1, b->map };
78 if (a->map->num_entries != b->map->num_entries) {
79 return 0;
80 }
81 st_foreach(a->map, HASH_FUNCTION_CAST st_equal_foreach, (st_data_t) & args);
82 return args.rval;
83 }
84
record_equal(struct avro_record_datum_t * a,struct avro_record_datum_t * b)85 static int record_equal(struct avro_record_datum_t *a,
86 struct avro_record_datum_t *b)
87 {
88 if (!avro_schema_equal(a->schema, b->schema)) {
89 return 0;
90 }
91
92 struct st_equal_args args = { 1, b->fields_byname };
93 if (a->fields_byname->num_entries != b->fields_byname->num_entries) {
94 return 0;
95 }
96 st_foreach(a->fields_byname, HASH_FUNCTION_CAST st_equal_foreach, (st_data_t) & args);
97 return args.rval;
98 }
99
enum_equal(struct avro_enum_datum_t * a,struct avro_enum_datum_t * b)100 static int enum_equal(struct avro_enum_datum_t *a, struct avro_enum_datum_t *b)
101 {
102 return avro_schema_equal(a->schema, b->schema) && a->value == b->value;
103 }
104
fixed_equal(struct avro_fixed_datum_t * a,struct avro_fixed_datum_t * b)105 static int fixed_equal(struct avro_fixed_datum_t *a,
106 struct avro_fixed_datum_t *b)
107 {
108 if (!avro_schema_equal(a->schema, b->schema)) {
109 return 0;
110 }
111
112 return a->size == b->size && memcmp(a->bytes, b->bytes, a->size) == 0;
113 }
114
union_equal(struct avro_union_datum_t * a,struct avro_union_datum_t * b)115 static int union_equal(struct avro_union_datum_t *a,
116 struct avro_union_datum_t *b)
117 {
118 if (!avro_schema_equal(a->schema, b->schema)) {
119 return 0;
120 }
121
122 return a->discriminant == b->discriminant && avro_datum_equal(a->value, b->value);
123 }
124
avro_datum_equal(const avro_datum_t a,const avro_datum_t b)125 int avro_datum_equal(const avro_datum_t a, const avro_datum_t b)
126 {
127 if (!(is_avro_datum(a) && is_avro_datum(b))) {
128 return 0;
129 }
130 if (avro_typeof(a) != avro_typeof(b)) {
131 return 0;
132 }
133 switch (avro_typeof(a)) {
134 case AVRO_STRING:
135 return strcmp(avro_datum_to_string(a)->s,
136 avro_datum_to_string(b)->s) == 0;
137 case AVRO_BYTES:
138 return (avro_datum_to_bytes(a)->size ==
139 avro_datum_to_bytes(b)->size)
140 && memcmp(avro_datum_to_bytes(a)->bytes,
141 avro_datum_to_bytes(b)->bytes,
142 avro_datum_to_bytes(a)->size) == 0;
143 case AVRO_INT32:
144 return avro_datum_to_int32(a)->i32 ==
145 avro_datum_to_int32(b)->i32;
146 case AVRO_INT64:
147 return avro_datum_to_int64(a)->i64 ==
148 avro_datum_to_int64(b)->i64;
149 case AVRO_FLOAT:
150 return avro_datum_to_float(a)->f == avro_datum_to_float(b)->f;
151 case AVRO_DOUBLE:
152 return avro_datum_to_double(a)->d == avro_datum_to_double(b)->d;
153 case AVRO_BOOLEAN:
154 return avro_datum_to_boolean(a)->i ==
155 avro_datum_to_boolean(b)->i;
156 case AVRO_NULL:
157 return 1;
158 case AVRO_ARRAY:
159 return array_equal(avro_datum_to_array(a),
160 avro_datum_to_array(b));
161 case AVRO_MAP:
162 return map_equal(avro_datum_to_map(a), avro_datum_to_map(b));
163
164 case AVRO_RECORD:
165 return record_equal(avro_datum_to_record(a),
166 avro_datum_to_record(b));
167
168 case AVRO_ENUM:
169 return enum_equal(avro_datum_to_enum(a), avro_datum_to_enum(b));
170
171 case AVRO_FIXED:
172 return fixed_equal(avro_datum_to_fixed(a),
173 avro_datum_to_fixed(b));
174
175 case AVRO_UNION:
176 return union_equal(avro_datum_to_union(a),
177 avro_datum_to_union(b));
178
179 case AVRO_LINK:
180 /*
181 * TODO
182 */
183 return 0;
184 }
185 return 0;
186 }
187