| /* |
| * 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 |
| * |
| * https://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_private.h" |
| #include <string.h> |
| #include "datum.h" |
| |
| static int |
| array_equal(struct avro_array_datum_t *a, struct avro_array_datum_t *b) |
| { |
| if (!avro_schema_equal(a->schema, b->schema)) { |
| return 0; |
| } |
| |
| long i; |
| |
| if (a->els->num_entries != b->els->num_entries) { |
| return 0; |
| } |
| for (i = 0; i < a->els->num_entries; i++) { |
| union { |
| st_data_t data; |
| avro_datum_t datum; |
| } ael, bel; |
| st_lookup(a->els, i, &ael.data); |
| st_lookup(b->els, i, &bel.data); |
| if (!avro_datum_equal(ael.datum, bel.datum)) { |
| return 0; |
| } |
| } |
| return 1; |
| } |
| |
| struct st_equal_args { |
| int rval; |
| st_table *st; |
| }; |
| |
| static int |
| st_equal_foreach(char *key, avro_datum_t datum, struct st_equal_args *args) |
| { |
| union { |
| avro_datum_t datum_other; |
| st_data_t data; |
| } val; |
| if (!st_lookup(args->st, (st_data_t) key, &(val.data))) { |
| args->rval = 0; |
| return ST_STOP; |
| } |
| if (!avro_datum_equal(datum, val.datum_other)) { |
| args->rval = 0; |
| return ST_STOP; |
| } |
| return ST_CONTINUE; |
| } |
| |
| static int map_equal(struct avro_map_datum_t *a, struct avro_map_datum_t *b) |
| { |
| if (!avro_schema_equal(a->schema, b->schema)) { |
| return 0; |
| } |
| |
| struct st_equal_args args = { 1, b->map }; |
| if (a->map->num_entries != b->map->num_entries) { |
| return 0; |
| } |
| st_foreach(a->map, HASH_FUNCTION_CAST st_equal_foreach, (st_data_t) & args); |
| return args.rval; |
| } |
| |
| static int record_equal(struct avro_record_datum_t *a, |
| struct avro_record_datum_t *b) |
| { |
| if (!avro_schema_equal(a->schema, b->schema)) { |
| return 0; |
| } |
| |
| struct st_equal_args args = { 1, b->fields_byname }; |
| if (a->fields_byname->num_entries != b->fields_byname->num_entries) { |
| return 0; |
| } |
| st_foreach(a->fields_byname, HASH_FUNCTION_CAST st_equal_foreach, (st_data_t) & args); |
| return args.rval; |
| } |
| |
| static int enum_equal(struct avro_enum_datum_t *a, struct avro_enum_datum_t *b) |
| { |
| return avro_schema_equal(a->schema, b->schema) && a->value == b->value; |
| } |
| |
| static int fixed_equal(struct avro_fixed_datum_t *a, |
| struct avro_fixed_datum_t *b) |
| { |
| if (!avro_schema_equal(a->schema, b->schema)) { |
| return 0; |
| } |
| |
| return a->size == b->size && memcmp(a->bytes, b->bytes, a->size) == 0; |
| } |
| |
| static int union_equal(struct avro_union_datum_t *a, |
| struct avro_union_datum_t *b) |
| { |
| if (!avro_schema_equal(a->schema, b->schema)) { |
| return 0; |
| } |
| |
| return a->discriminant == b->discriminant && avro_datum_equal(a->value, b->value); |
| } |
| |
| int avro_datum_equal(const avro_datum_t a, const avro_datum_t b) |
| { |
| if (!(is_avro_datum(a) && is_avro_datum(b))) { |
| return 0; |
| } |
| if (avro_typeof(a) != avro_typeof(b)) { |
| return 0; |
| } |
| switch (avro_typeof(a)) { |
| case AVRO_STRING: |
| return strcmp(avro_datum_to_string(a)->s, |
| avro_datum_to_string(b)->s) == 0; |
| case AVRO_BYTES: |
| return (avro_datum_to_bytes(a)->size == |
| avro_datum_to_bytes(b)->size) |
| && memcmp(avro_datum_to_bytes(a)->bytes, |
| avro_datum_to_bytes(b)->bytes, |
| avro_datum_to_bytes(a)->size) == 0; |
| case AVRO_INT32: |
| return avro_datum_to_int32(a)->i32 == |
| avro_datum_to_int32(b)->i32; |
| case AVRO_INT64: |
| return avro_datum_to_int64(a)->i64 == |
| avro_datum_to_int64(b)->i64; |
| case AVRO_FLOAT: |
| return avro_datum_to_float(a)->f == avro_datum_to_float(b)->f; |
| case AVRO_DOUBLE: |
| return avro_datum_to_double(a)->d == avro_datum_to_double(b)->d; |
| case AVRO_BOOLEAN: |
| return avro_datum_to_boolean(a)->i == |
| avro_datum_to_boolean(b)->i; |
| case AVRO_NULL: |
| return 1; |
| case AVRO_ARRAY: |
| return array_equal(avro_datum_to_array(a), |
| avro_datum_to_array(b)); |
| case AVRO_MAP: |
| return map_equal(avro_datum_to_map(a), avro_datum_to_map(b)); |
| |
| case AVRO_RECORD: |
| return record_equal(avro_datum_to_record(a), |
| avro_datum_to_record(b)); |
| |
| case AVRO_ENUM: |
| return enum_equal(avro_datum_to_enum(a), avro_datum_to_enum(b)); |
| |
| case AVRO_FIXED: |
| return fixed_equal(avro_datum_to_fixed(a), |
| avro_datum_to_fixed(b)); |
| |
| case AVRO_UNION: |
| return union_equal(avro_datum_to_union(a), |
| avro_datum_to_union(b)); |
| |
| case AVRO_LINK: |
| /* |
| * TODO |
| */ |
| return 0; |
| } |
| return 0; |
| } |