blob: f63a83a56aeaaf8f24bc844736a31bfe75f6fa49 [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 <errno.h>
#include <string.h>
#include "avro/data.h"
#include "avro/allocation.h"
#include "avro/errors.h"
#include "st.h"
#define raw_entry_size(element_size) \
(sizeof(avro_raw_map_entry_t) + element_size)
void avro_raw_map_init(avro_raw_map_t *map, size_t element_size)
{
memset(map, 0, sizeof(avro_raw_map_t));
avro_raw_array_init(&map->elements, raw_entry_size(element_size));
map->indices_by_key = st_init_strtable();
}
static void
avro_raw_map_free_keys(avro_raw_map_t *map)
{
unsigned int i;
for (i = 0; i < avro_raw_map_size(map); i++) {
void *ventry =
((char *) map->elements.data + map->elements.element_size * i);
avro_raw_map_entry_t *entry = (avro_raw_map_entry_t *) ventry;
avro_str_free((char *) entry->key);
}
}
void avro_raw_map_done(avro_raw_map_t *map)
{
avro_raw_map_free_keys(map);
avro_raw_array_done(&map->elements);
st_free_table((st_table *) map->indices_by_key);
memset(map, 0, sizeof(avro_raw_map_t));
}
void avro_raw_map_clear(avro_raw_map_t *map)
{
avro_raw_map_free_keys(map);
avro_raw_array_clear(&map->elements);
st_free_table((st_table *) map->indices_by_key);
map->indices_by_key = st_init_strtable();
}
int
avro_raw_map_ensure_size(avro_raw_map_t *map, size_t desired_count)
{
return avro_raw_array_ensure_size(&map->elements, desired_count);
}
void *avro_raw_map_get(const avro_raw_map_t *map, const char *key,
size_t *index)
{
st_data_t data;
if (st_lookup((st_table *) map->indices_by_key, (st_data_t) key, &data)) {
unsigned int i = (unsigned int) data;
if (index) {
*index = i;
}
void *raw_entry =
((char *) map->elements.data + map->elements.element_size * i);
return (char *) raw_entry + sizeof(avro_raw_map_entry_t);
} else {
return NULL;
}
}
int avro_raw_map_get_or_create(avro_raw_map_t *map, const char *key,
void **element, size_t *index)
{
st_data_t data;
void *el;
unsigned int i;
int is_new;
if (st_lookup((st_table *) map->indices_by_key, (st_data_t) key, &data)) {
i = (unsigned int) data;
void *raw_entry =
((char *) map->elements.data + map->elements.element_size * i);
el = (char *) raw_entry + sizeof(avro_raw_map_entry_t);
is_new = 0;
} else {
i = map->elements.element_count;
avro_raw_map_entry_t *raw_entry =
(avro_raw_map_entry_t *) avro_raw_array_append(&map->elements);
raw_entry->key = avro_strdup(key);
st_insert((st_table *) map->indices_by_key,
(st_data_t) raw_entry->key, (st_data_t) i);
if (!raw_entry) {
avro_str_free((char*)raw_entry->key);
return -ENOMEM;
}
el = ((char *) raw_entry) + sizeof(avro_raw_map_entry_t);
is_new = 1;
}
if (element) {
*element = el;
}
if (index) {
*index = i;
}
return is_new;
}