/*
 *  Copyright 1996, University Corporation for Atmospheric Research
 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
 */
/* $Id: string.c,v 1.1 2010-01-06 16:34:07 kwleiter 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 != '+' && 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;
}
