/*
 *	Copyright 1996, University Corporation for Atmospheric Research
 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
 */
/* $Id: string.c,v 1.58 2003/06/10 15:31:21 russ Exp $ */

#include "nc.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "ncx.h"
#include "rnd.h"


/*
 * Free string, and, if needed, its values.
 * Formerly
NC_free_string()
 */
void
free_NC_string(NC_string *ncstrp)
{
	if(ncstrp==NULL)
		return;
	free(ncstrp);
}


/*
 * Verify that a name string is valid
 * CDL syntax, eg, all the characters are
 * alphanumeric, '-', '_', or '.'.
 * Also permit ':', '@', '(', or ')' in names for chemists currently making 
 * use of these characters, but don't document until ncgen and ncdump can 
 * also handle these characters in names.
 */
int
NC_check_name(const char *name)
{
	const char *cp = name;
	assert(name != NULL);

	if(*name == 0)
		return NC_EBADNAME; /* empty names disallowed */

	for(; *cp != 0; cp++)
	{
		int ch = *cp;
		if(!isalnum(ch))
		{
			if(ch != '_' && ch != '-' && ch != '.')
			if(ch != '_' && ch != '-' && ch != '.' && 
			   ch != ':' && ch != '@' && ch != '(' && ch != ')')
				return NC_EBADNAME;
		}
	}
	if(cp - name > NC_MAX_NAME)
		return NC_EMAXNAME;

	return NC_NOERR;
}


/*
 * Allocate a NC_string structure large enough
 * to hold slen characters.
 * Formerly
NC_new_string(count, str)
 */
NC_string *
new_NC_string(size_t slen, const char *str)
{
	NC_string *ncstrp;
	size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1;

#if 0
	sz = _RNDUP(sz, X_ALIGN);
#endif
		
	ncstrp = (NC_string *)malloc(sz);
	if( ncstrp == NULL )
		return NULL;
	(void) memset(ncstrp, 0, sz);

	ncstrp->nchars = sz - M_RNDUP(sizeof(NC_string)) - 1;
	assert(ncstrp->nchars + 1 > slen);
	ncstrp->cp = (char *)ncstrp + M_RNDUP(sizeof(NC_string));

	if(str != NULL && *str != 0)
	{
		(void) strncpy(ncstrp->cp, str, ncstrp->nchars +1);
		ncstrp->cp[ncstrp->nchars] = 0;
	}
	
	return(ncstrp);
}


/*
 * If possible, change the value of an NC_string to 'str'.
 *
 * Formerly
NC_re_string()
 */
int
set_NC_string(NC_string *ncstrp, const char *str)
{
	size_t slen;
	size_t diff;

	assert(str != NULL && *str != 0);

	slen = strlen(str);

	if(ncstrp->nchars < slen)
		return NC_ENOTINDEFINE;

	(void) memcpy(ncstrp->cp, str, slen);
	diff = ncstrp->nchars - slen;
	if(diff != 0)
		(void) memset(ncstrp->cp + slen, 0, diff);

	return NC_NOERR;
}
