/*
 * 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;
}
