/* 
 * Copyright 2008-2018 Aerospike, Inc.
 *
 * Portions may be licensed to Aerospike, Inc. under one or more contributor
 * license agreements.
 *
 * Licensed 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 <aerospike/as_geojson.h>
#include <citrusleaf/alloc.h>
#include <string.h>

/******************************************************************************
 *	INLINE FUNCTIONS
 *****************************************************************************/

extern inline void			as_geojson_destroy(as_geojson * string);

extern inline char *		as_geojson_getorelse(const as_geojson * string, char * fallback);
extern inline char *		as_geojson_get(const as_geojson * string);

extern inline as_val *		as_geojson_toval(const as_geojson * string);
extern inline as_geojson *	as_geojson_fromval(const as_val * v);

/******************************************************************************
 *	INSTANCE FUNCTIONS
 *****************************************************************************/

static inline as_geojson * as_geojson_cons(as_geojson * string, bool free, char * value, size_t len, bool value_free)
{
	if ( !string ) return string;

	as_val_cons((as_val *) string, AS_GEOJSON, free);
	string->free = value_free;
	string->value = value;
	string->len = len;
	return string;
}

as_geojson * as_geojson_init(as_geojson * string, char * value, bool free)
{
	return as_geojson_cons(string, false, value, SIZE_MAX, free);
}

as_geojson * as_geojson_init_wlen(as_geojson * string, char * value, size_t len, bool free)
{
	return as_geojson_cons(string, false, value, len, free);
}

as_geojson * as_geojson_new(char * value, bool free)
{
	as_geojson * string = (as_geojson *) cf_malloc(sizeof(as_geojson));
	return as_geojson_cons(string, true, value, SIZE_MAX, free);
}

as_geojson * as_geojson_new_wlen(char * value, size_t len, bool free)
{
	as_geojson * string = (as_geojson *) cf_malloc(sizeof(as_geojson));
	return as_geojson_cons(string, true, value, len, free);
}

as_geojson *as_geojson_new_strdup(const char * s)
{
	return as_geojson_new(cf_strdup(s), true);
}

/******************************************************************************
 *	VALUE FUNCTIONS
 ******************************************************************************/

size_t as_geojson_len(as_geojson * string)
{
	if (string->value == NULL) {
		return 0;
	}
	if (string->len == SIZE_MAX) {
		string->len = strlen(string->value);
	}
	return string->len;
}

/******************************************************************************
 *	as_val FUNCTIONS
 ******************************************************************************/

void as_geojson_val_destroy(as_val * v)
{
	as_geojson * string = as_geojson_fromval(v);
	if ( !string ) return;

	if ( string->value && string->free ) {
		cf_free(string->value);
	}
	
	string->value = NULL;
	string->free = false;
}

uint32_t as_geojson_val_hashcode(const as_val * v)
{
	as_geojson * string = as_geojson_fromval(v);
	if ( string == NULL || string->value == NULL) return 0;
	uint32_t hash = 0;
	int c;
	char * str = string->value;
	while ( (c = *str++) ) {
		hash = c + (hash << 6) + (hash << 16) - hash;
	}
	return hash;
}

char * as_geojson_val_tostring(const as_val * v)
{
	as_geojson * s = (as_geojson *) v;
	if (s->value == NULL) return(NULL);
	size_t sl = as_geojson_len(s);
	size_t st = 3 + sl;
	char * str = (char *) cf_malloc(sizeof(char) * st);
	if (!str) return str;
	*(str + 0) = '\"';
	strcpy(str + 1, s->value);
	*(str + 1 + sl) = '\"';
	*(str + 1 + sl + 1) = '\0';
	return str;
}
