Blame trio/triostr.c

Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 *
Packit 8f70b4
 * $Id: triostr.c,v 1.17 2002/05/20 12:03:38 breese Exp $
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
Packit 8f70b4
 *
Packit 8f70b4
 * Permission to use, copy, modify, and distribute this software for any
Packit 8f70b4
 * purpose with or without fee is hereby granted, provided that the above
Packit 8f70b4
 * copyright notice and this permission notice appear in all copies.
Packit 8f70b4
 *
Packit 8f70b4
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
Packit 8f70b4
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
Packit 8f70b4
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
Packit 8f70b4
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
Packit 8f70b4
 *
Packit 8f70b4
 ************************************************************************/
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Include files
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#include <assert.h>
Packit 8f70b4
#include <stdlib.h>
Packit 8f70b4
#include <string.h>
Packit 8f70b4
#include <ctype.h>
Packit 8f70b4
#include <math.h>
Packit 8f70b4
#include "triodef.h"
Packit 8f70b4
#include "triostr.h"
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Definitions
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_STRING_PUBLIC)
Packit 8f70b4
# define TRIO_STRING_PUBLIC TRIO_PUBLIC
Packit 8f70b4
#endif
Packit 8f70b4
#if !defined(TRIO_STRING_PRIVATE)
Packit 8f70b4
# define TRIO_STRING_PRIVATE TRIO_PRIVATE
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#if !defined(NULL)
Packit 8f70b4
# define NULL 0
Packit 8f70b4
#endif
Packit 8f70b4
#if !defined(NIL)
Packit 8f70b4
# define NIL ((char)0)
Packit 8f70b4
#endif
Packit 8f70b4
#if !defined(FALSE)
Packit 8f70b4
# define FALSE (1 == 0)
Packit 8f70b4
# define TRUE (! FALSE)
Packit 8f70b4
#endif
Packit 8f70b4
#if !defined(BOOLEAN_T)
Packit 8f70b4
# define BOOLEAN_T int
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#if defined(TRIO_COMPILER_SUPPORTS_C99)
Packit 8f70b4
# define USE_STRTOD
Packit 8f70b4
# define USE_STRTOF
Packit 8f70b4
#elif defined(TRIO_COMPILER_MSVC)
Packit 8f70b4
# define USE_STRTOD
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#if defined(TRIO_PLATFORM_UNIX)
Packit 8f70b4
# define USE_STRCASECMP
Packit 8f70b4
# define USE_STRNCASECMP
Packit 8f70b4
# define USE_STRERROR
Packit 8f70b4
# if defined(TRIO_PLATFORM_QNX)
Packit 8f70b4
#  define strcasecmp(x,y) stricmp(x,y)
Packit 8f70b4
#  define strncasecmp(x,y,n) strnicmp(x,y,n)
Packit 8f70b4
# endif
Packit 8f70b4
#elif defined(TRIO_PLATFORM_WIN32)
Packit 8f70b4
# define USE_STRCASECMP
Packit 8f70b4
# define strcasecmp(x,y) strcmpi(x,y)
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Structures
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
struct _trio_string_t
Packit 8f70b4
{
Packit 8f70b4
  char *content;
Packit 8f70b4
  size_t length;
Packit 8f70b4
  size_t allocated;
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Constants
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.17 2002/05/20 12:03:38 breese Exp $";
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Static String Functions
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#if defined(TRIO_DOCUMENTATION)
Packit 8f70b4
# include "doc/doc_static.h"
Packit 8f70b4
#endif
Packit 8f70b4
/** @addtogroup StaticStrings
Packit 8f70b4
    @{
Packit 8f70b4
*/
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Create new string.
Packit 8f70b4
Packit 8f70b4
   @param size Size of new string.
Packit 8f70b4
   @return Pointer to string, or NULL if allocation failed.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_create
Packit 8f70b4
TRIO_ARGS1((size),
Packit 8f70b4
	   size_t size)
Packit 8f70b4
{
Packit 8f70b4
  return (char *)TRIO_MALLOC(size);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Destroy string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be freed.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC void
Packit 8f70b4
trio_destroy
Packit 8f70b4
TRIO_ARGS1((string),
Packit 8f70b4
	   char *string)
Packit 8f70b4
{
Packit 8f70b4
  if (string)
Packit 8f70b4
    {
Packit 8f70b4
      TRIO_FREE(string);
Packit 8f70b4
    }
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Count the number of characters in a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to measure.
Packit 8f70b4
   @return Number of characters in @string.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC size_t
Packit 8f70b4
trio_length
Packit 8f70b4
TRIO_ARGS1((string),
Packit 8f70b4
	   TRIO_CONST char *string)
Packit 8f70b4
{
Packit 8f70b4
  return strlen(string);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Append @p source at the end of @p target.
Packit 8f70b4
   
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
   
Packit 8f70b4
   @pre @p target must point to a memory chunk with sufficient room to
Packit 8f70b4
   contain the @p target string and @p source string.
Packit 8f70b4
   @pre No boundary checking is performed, so insufficient memory will
Packit 8f70b4
   result in a buffer overrun.
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_append
Packit 8f70b4
TRIO_ARGS2((target, source),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   TRIO_CONST char *source)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(source);
Packit 8f70b4
  
Packit 8f70b4
  return (strcat(target, source) != NULL);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Append at most @p max characters from @p source to @p target.
Packit 8f70b4
   
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param max Maximum number of characters to append.
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
   
Packit 8f70b4
   @pre @p target must point to a memory chuck with sufficient room to
Packit 8f70b4
   contain the @p target string and the @p source string (at most @p max
Packit 8f70b4
   characters).
Packit 8f70b4
   @pre No boundary checking is performed, so insufficient memory will
Packit 8f70b4
   result in a buffer overrun.
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_append_max
Packit 8f70b4
TRIO_ARGS3((target, max, source),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *source)
Packit 8f70b4
{
Packit 8f70b4
  size_t length;
Packit 8f70b4
  
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(source);
Packit 8f70b4
Packit 8f70b4
  length = trio_length(target);
Packit 8f70b4
  
Packit 8f70b4
  if (max > length)
Packit 8f70b4
    {
Packit 8f70b4
      strncat(target, source, max - length - 1);
Packit 8f70b4
    }
Packit 8f70b4
  return TRUE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Determine if a string contains a substring.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param substring String to be found.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_contains
Packit 8f70b4
TRIO_ARGS2((string, substring),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   TRIO_CONST char *substring)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert(substring);
Packit 8f70b4
  
Packit 8f70b4
  return (0 != strstr(string, substring));
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Copy @p source to @p target.
Packit 8f70b4
   
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
   
Packit 8f70b4
   @pre @p target must point to a memory chunk with sufficient room to
Packit 8f70b4
   contain the @p source string.
Packit 8f70b4
   @pre No boundary checking is performed, so insufficient memory will
Packit 8f70b4
   result in a buffer overrun.
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_copy
Packit 8f70b4
TRIO_ARGS2((target, source),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   TRIO_CONST char *source)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(source);
Packit 8f70b4
     
Packit 8f70b4
  (void)strcpy(target, source);
Packit 8f70b4
  return TRUE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Copy at most @p max characters from @p source to @p target.
Packit 8f70b4
   
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param max Maximum number of characters to append.
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
   
Packit 8f70b4
   @pre @p target must point to a memory chunk with sufficient room to
Packit 8f70b4
   contain the @p source string (at most @p max characters).
Packit 8f70b4
   @pre No boundary checking is performed, so insufficient memory will
Packit 8f70b4
   result in a buffer overrun.
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_copy_max
Packit 8f70b4
TRIO_ARGS3((target, max, source),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *source)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(source);
Packit 8f70b4
  assert(max > 0); /* Includes != 0 */
Packit 8f70b4
Packit 8f70b4
  (void)strncpy(target, source, max - 1);
Packit 8f70b4
  target[max - 1] = (char)0;
Packit 8f70b4
  return TRUE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * TrioDuplicateMax
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PRIVATE char *
Packit 8f70b4
TrioDuplicateMax
Packit 8f70b4
TRIO_ARGS2((source, size),
Packit 8f70b4
	   TRIO_CONST char *source,
Packit 8f70b4
	   size_t size)
Packit 8f70b4
{
Packit 8f70b4
  char *target;
Packit 8f70b4
Packit 8f70b4
  assert(source);
Packit 8f70b4
Packit 8f70b4
  /* Make room for string plus a terminating zero */
Packit 8f70b4
  size++;
Packit 8f70b4
  target = trio_create(size);
Packit 8f70b4
  if (target)
Packit 8f70b4
    {
Packit 8f70b4
      trio_copy_max(target, size, source);
Packit 8f70b4
    }
Packit 8f70b4
  return target;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Duplicate @p source.
Packit 8f70b4
   
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @return A copy of the @p source string.
Packit 8f70b4
   
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_duplicate
Packit 8f70b4
TRIO_ARGS1((source),
Packit 8f70b4
	   TRIO_CONST char *source)
Packit 8f70b4
{
Packit 8f70b4
  return TrioDuplicateMax(source, trio_length(source));
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Duplicate at most @p max characters of @p source.
Packit 8f70b4
   
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @param max Maximum number of characters to duplicate.
Packit 8f70b4
   @return A copy of the @p source string.
Packit 8f70b4
   
Packit 8f70b4
   @post @p target will be zero terminated.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_duplicate_max TRIO_ARGS2((source, max),
Packit 8f70b4
			      TRIO_CONST char *source,
Packit 8f70b4
			      size_t max)
Packit 8f70b4
{
Packit 8f70b4
  size_t length;
Packit 8f70b4
Packit 8f70b4
  assert(source);
Packit 8f70b4
  assert(max > 0);
Packit 8f70b4
Packit 8f70b4
  length = trio_length(source);
Packit 8f70b4
  if (length > max)
Packit 8f70b4
    {
Packit 8f70b4
      length = max;
Packit 8f70b4
    }
Packit 8f70b4
  return TrioDuplicateMax(source, length);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Compare if two strings are equal.
Packit 8f70b4
   
Packit 8f70b4
   @param first First string.
Packit 8f70b4
   @param second Second string.
Packit 8f70b4
   @return Boolean indicating whether the two strings are equal or not.
Packit 8f70b4
   
Packit 8f70b4
   Case-insensitive comparison.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_equal
Packit 8f70b4
TRIO_ARGS2((first, second),
Packit 8f70b4
	   TRIO_CONST char *first,
Packit 8f70b4
	   TRIO_CONST char *second)
Packit 8f70b4
{
Packit 8f70b4
  assert(first);
Packit 8f70b4
  assert(second);
Packit 8f70b4
Packit 8f70b4
  if ((first != NULL) && (second != NULL))
Packit 8f70b4
    {
Packit 8f70b4
#if defined(USE_STRCASECMP)
Packit 8f70b4
      return (0 == strcasecmp(first, second));
Packit 8f70b4
#else
Packit 8f70b4
      while ((*first != NIL) && (*second != NIL))
Packit 8f70b4
	{
Packit 8f70b4
	  if (toupper(*first) != toupper(*second))
Packit 8f70b4
	    {
Packit 8f70b4
	      break;
Packit 8f70b4
	    }
Packit 8f70b4
	  first++;
Packit 8f70b4
	  second++;
Packit 8f70b4
	}
Packit 8f70b4
      return ((*first == NIL) && (*second == NIL));
Packit 8f70b4
#endif
Packit 8f70b4
    }
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Compare if two strings are equal.
Packit 8f70b4
   
Packit 8f70b4
   @param first First string.
Packit 8f70b4
   @param second Second string.
Packit 8f70b4
   @return Boolean indicating whether the two strings are equal or not.
Packit 8f70b4
   
Packit 8f70b4
   Case-sensitive comparison.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_equal_case
Packit 8f70b4
TRIO_ARGS2((first, second),
Packit 8f70b4
	   TRIO_CONST char *first,
Packit 8f70b4
	   TRIO_CONST char *second)
Packit 8f70b4
{
Packit 8f70b4
  assert(first);
Packit 8f70b4
  assert(second);
Packit 8f70b4
Packit 8f70b4
  if ((first != NULL) && (second != NULL))
Packit 8f70b4
    {
Packit 8f70b4
      return (0 == strcmp(first, second));
Packit 8f70b4
    }
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Compare if two strings up until the first @p max characters are equal.
Packit 8f70b4
   
Packit 8f70b4
   @param first First string.
Packit 8f70b4
   @param max Maximum number of characters to compare.
Packit 8f70b4
   @param second Second string.
Packit 8f70b4
   @return Boolean indicating whether the two strings are equal or not.
Packit 8f70b4
   
Packit 8f70b4
   Case-sensitive comparison.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_equal_case_max
Packit 8f70b4
TRIO_ARGS3((first, max, second),
Packit 8f70b4
	   TRIO_CONST char *first,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *second)
Packit 8f70b4
{
Packit 8f70b4
  assert(first);
Packit 8f70b4
  assert(second);
Packit 8f70b4
Packit 8f70b4
  if ((first != NULL) && (second != NULL))
Packit 8f70b4
    {
Packit 8f70b4
      return (0 == strncmp(first, second, max));
Packit 8f70b4
    }
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Compare if two strings are equal.
Packit 8f70b4
   
Packit 8f70b4
   @param first First string.
Packit 8f70b4
   @param second Second string.
Packit 8f70b4
   @return Boolean indicating whether the two strings are equal or not.
Packit 8f70b4
Packit 8f70b4
   Collating characters are considered equal.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_equal_locale
Packit 8f70b4
TRIO_ARGS2((first, second),
Packit 8f70b4
	   TRIO_CONST char *first,
Packit 8f70b4
	   TRIO_CONST char *second)
Packit 8f70b4
{
Packit 8f70b4
  assert(first);
Packit 8f70b4
  assert(second);
Packit 8f70b4
Packit 8f70b4
#if defined(LC_COLLATE)
Packit 8f70b4
  return (strcoll(first, second) == 0);
Packit 8f70b4
#else
Packit 8f70b4
  return trio_equal(first, second);
Packit 8f70b4
#endif
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Compare if two strings up until the first @p max characters are equal.
Packit 8f70b4
   
Packit 8f70b4
   @param first First string.
Packit 8f70b4
   @param max Maximum number of characters to compare.
Packit 8f70b4
   @param second Second string.
Packit 8f70b4
   @return Boolean indicating whether the two strings are equal or not.
Packit 8f70b4
   
Packit 8f70b4
   Case-insensitive comparison.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_equal_max
Packit 8f70b4
TRIO_ARGS3((first, max, second),
Packit 8f70b4
	   TRIO_CONST char *first,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *second)
Packit 8f70b4
{
Packit 8f70b4
  assert(first);
Packit 8f70b4
  assert(second);
Packit 8f70b4
Packit 8f70b4
  if ((first != NULL) && (second != NULL))
Packit 8f70b4
    {
Packit 8f70b4
#if defined(USE_STRNCASECMP)
Packit 8f70b4
      return (0 == strncasecmp(first, second, max));
Packit 8f70b4
#else
Packit 8f70b4
      /* Not adequately tested yet */
Packit 8f70b4
      size_t cnt = 0;
Packit 8f70b4
      while ((*first != NIL) && (*second != NIL) && (cnt <= max))
Packit 8f70b4
	{
Packit 8f70b4
	  if (toupper(*first) != toupper(*second))
Packit 8f70b4
	    {
Packit 8f70b4
	      break;
Packit 8f70b4
	    }
Packit 8f70b4
	  first++;
Packit 8f70b4
	  second++;
Packit 8f70b4
	  cnt++;
Packit 8f70b4
	}
Packit 8f70b4
      return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
Packit 8f70b4
#endif
Packit 8f70b4
    }
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Provide a textual description of an error code (errno).
Packit 8f70b4
Packit 8f70b4
   @param error_number Error number.
Packit 8f70b4
   @return Textual description of @p error_number.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC TRIO_CONST char *
Packit 8f70b4
trio_error
Packit 8f70b4
TRIO_ARGS1((error_number),
Packit 8f70b4
	   int error_number)
Packit 8f70b4
{
Packit 8f70b4
#if defined(USE_STRERROR)
Packit 8f70b4
  return strerror(error_number);
Packit 8f70b4
#else
Packit 8f70b4
  return "unknown";
Packit 8f70b4
#endif
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Format the date/time according to @p format.
Packit 8f70b4
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param max Maximum number of characters to format.
Packit 8f70b4
   @param format Formatting string.
Packit 8f70b4
   @param datetime Date/time structure.
Packit 8f70b4
   @return Number of formatted characters.
Packit 8f70b4
Packit 8f70b4
   The formatting string accepts the same specifiers as the standard C
Packit 8f70b4
   function strftime.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC size_t
Packit 8f70b4
trio_format_date_max
Packit 8f70b4
TRIO_ARGS4((target, max, format, datetime),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *format,
Packit 8f70b4
	   TRIO_CONST struct tm *datetime)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(format);
Packit 8f70b4
  assert(datetime);
Packit 8f70b4
  assert(max > 0);
Packit 8f70b4
  
Packit 8f70b4
  return strftime(target, max, format, datetime);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Calculate a hash value for a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be calculated on.
Packit 8f70b4
   @param type Hash function.
Packit 8f70b4
   @return Calculated hash value.
Packit 8f70b4
Packit 8f70b4
   @p type can be one of the following
Packit 8f70b4
   @li @c TRIO_HASH_PLAIN Plain hash function.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC unsigned long
Packit 8f70b4
trio_hash
Packit 8f70b4
TRIO_ARGS2((string, type),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   int type)
Packit 8f70b4
{
Packit 8f70b4
  unsigned long value = 0L;
Packit 8f70b4
  char ch;
Packit 8f70b4
Packit 8f70b4
  assert(string);
Packit 8f70b4
  
Packit 8f70b4
  switch (type)
Packit 8f70b4
    {
Packit 8f70b4
    case TRIO_HASH_PLAIN:
Packit 8f70b4
      while ( (ch = *string++) != NIL )
Packit 8f70b4
	{
Packit 8f70b4
	  value *= 31;
Packit 8f70b4
	  value += (unsigned long)ch;
Packit 8f70b4
	}
Packit 8f70b4
      break;
Packit 8f70b4
    default:
Packit 8f70b4
      assert(FALSE);
Packit 8f70b4
      break;
Packit 8f70b4
    }
Packit 8f70b4
  return value;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Find first occurrence of a character in a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param character Character to be found.
Packit 8f70b4
   @param A pointer to the found character, or NULL if character was not found.
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_index
Packit 8f70b4
TRIO_ARGS2((string, character),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   int character)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
Packit 8f70b4
  return strchr(string, character);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Find last occurrence of a character in a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param character Character to be found.
Packit 8f70b4
   @param A pointer to the found character, or NULL if character was not found.
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_index_last
Packit 8f70b4
TRIO_ARGS2((string, character),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   int character)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
Packit 8f70b4
  return strchr(string, character);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Convert the alphabetic letters in the string to lower-case.
Packit 8f70b4
Packit 8f70b4
   @param target String to be converted.
Packit 8f70b4
   @return Number of processed characters (converted or not).
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_lower
Packit 8f70b4
TRIO_ARGS1((target),
Packit 8f70b4
	   char *target)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
Packit 8f70b4
  return trio_span_function(target, target, tolower);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Compare two strings using wildcards.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param pattern Pattern, including wildcards, to search for.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
Packit 8f70b4
   Case-insensitive comparison.
Packit 8f70b4
   
Packit 8f70b4
   The following wildcards can be used
Packit 8f70b4
   @li @c * Match any number of characters.
Packit 8f70b4
   @li @c ? Match a single character.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_match
Packit 8f70b4
TRIO_ARGS2((string, pattern),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   TRIO_CONST char *pattern)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert(pattern);
Packit 8f70b4
  
Packit 8f70b4
  for (; ('*' != *pattern); ++pattern, ++string)
Packit 8f70b4
    {
Packit 8f70b4
      if (NIL == *string)
Packit 8f70b4
	{
Packit 8f70b4
	  return (NIL == *pattern);
Packit 8f70b4
	}
Packit 8f70b4
      if ((toupper((int)*string) != toupper((int)*pattern))
Packit 8f70b4
	  && ('?' != *pattern))
Packit 8f70b4
	{
Packit 8f70b4
	  return FALSE;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  /* two-line patch to prevent *too* much recursiveness: */
Packit 8f70b4
  while ('*' == pattern[1])
Packit 8f70b4
    pattern++;
Packit 8f70b4
Packit 8f70b4
  do
Packit 8f70b4
    {
Packit 8f70b4
      if ( trio_match(string, &pattern[1]) )
Packit 8f70b4
	{
Packit 8f70b4
	  return TRUE;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  while (*string++);
Packit 8f70b4
  
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Compare two strings using wildcards.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param pattern Pattern, including wildcards, to search for.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
Packit 8f70b4
   Case-sensitive comparison.
Packit 8f70b4
   
Packit 8f70b4
   The following wildcards can be used
Packit 8f70b4
   @li @c * Match any number of characters.
Packit 8f70b4
   @li @c ? Match a single character.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_match_case
Packit 8f70b4
TRIO_ARGS2((string, pattern),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   TRIO_CONST char *pattern)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert(pattern);
Packit 8f70b4
  
Packit 8f70b4
  for (; ('*' != *pattern); ++pattern, ++string)
Packit 8f70b4
    {
Packit 8f70b4
      if (NIL == *string)
Packit 8f70b4
	{
Packit 8f70b4
	  return (NIL == *pattern);
Packit 8f70b4
	}
Packit 8f70b4
      if ((*string != *pattern)
Packit 8f70b4
	  && ('?' != *pattern))
Packit 8f70b4
	{
Packit 8f70b4
	  return FALSE;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  /* two-line patch to prevent *too* much recursiveness: */
Packit 8f70b4
  while ('*' == pattern[1])
Packit 8f70b4
    pattern++;
Packit 8f70b4
Packit 8f70b4
  do
Packit 8f70b4
    {
Packit 8f70b4
      if ( trio_match_case(string, &pattern[1]) )
Packit 8f70b4
	{
Packit 8f70b4
	  return TRUE;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  while (*string++);
Packit 8f70b4
  
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Execute a function on each character in string.
Packit 8f70b4
Packit 8f70b4
   @param target Target string.
Packit 8f70b4
   @param source Source string.
Packit 8f70b4
   @param Function Function to be executed.
Packit 8f70b4
   @return Number of processed characters.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC size_t
Packit 8f70b4
trio_span_function
Packit 8f70b4
TRIO_ARGS3((target, source, Function),
Packit 8f70b4
	   char *target,
Packit 8f70b4
	   TRIO_CONST char *source,
Packit 8f70b4
	   int (*Function) TRIO_PROTO((int)))
Packit 8f70b4
{
Packit 8f70b4
  size_t count = 0;
Packit 8f70b4
Packit 8f70b4
  assert(target);
Packit 8f70b4
  assert(source);
Packit 8f70b4
  assert(Function);
Packit 8f70b4
  
Packit 8f70b4
  while (*source != NIL)
Packit 8f70b4
    {
Packit 8f70b4
      *target++ = Function(*source++);
Packit 8f70b4
      count++;
Packit 8f70b4
    }
Packit 8f70b4
  return count;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Search for a substring in a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param substring String to be found.
Packit 8f70b4
   @return Pointer to first occurrence of @p substring in @p string, or NULL
Packit 8f70b4
   if no match was found.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_substring
Packit 8f70b4
TRIO_ARGS2((string, substring),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   TRIO_CONST char *substring)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert(substring);
Packit 8f70b4
Packit 8f70b4
  return strstr(string, substring);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Search for a substring in the first @p max characters of a string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be searched.
Packit 8f70b4
   @param max Maximum characters to be searched.
Packit 8f70b4
   @param substring String to be found.
Packit 8f70b4
   @return Pointer to first occurrence of @p substring in @p string, or NULL
Packit 8f70b4
   if no match was found.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_substring_max
Packit 8f70b4
TRIO_ARGS3((string, max, substring),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *substring)
Packit 8f70b4
{
Packit 8f70b4
  size_t count;
Packit 8f70b4
  size_t size;
Packit 8f70b4
  char *result = NULL;
Packit 8f70b4
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert(substring);
Packit 8f70b4
  
Packit 8f70b4
  size = trio_length(substring);
Packit 8f70b4
  if (size <= max)
Packit 8f70b4
    {
Packit 8f70b4
      for (count = 0; count <= max - size; count++)
Packit 8f70b4
	{
Packit 8f70b4
	  if (trio_equal_max(substring, size, &string[count]))
Packit 8f70b4
	    {
Packit 8f70b4
	      result = (char *)&string[count];
Packit 8f70b4
	      break;
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  return result;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Tokenize string.
Packit 8f70b4
Packit 8f70b4
   @param string String to be tokenized.
Packit 8f70b4
   @param tokens String containing list of delimiting characters.
Packit 8f70b4
   @return Start of new token.
Packit 8f70b4
Packit 8f70b4
   @warning @p string will be destroyed.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_tokenize
Packit 8f70b4
TRIO_ARGS2((string, delimiters),
Packit 8f70b4
	   char *string,
Packit 8f70b4
	   TRIO_CONST char *delimiters)
Packit 8f70b4
{
Packit 8f70b4
  assert(delimiters);
Packit 8f70b4
  
Packit 8f70b4
  return strtok(string, delimiters);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Convert string to floating-point number.
Packit 8f70b4
Packit 8f70b4
   @param source String to be converted.
Packit 8f70b4
   @param endp Pointer to end of the converted string.
Packit 8f70b4
   @return A floating-point number.
Packit 8f70b4
Packit 8f70b4
   The following Extended Backus-Naur form is used
Packit 8f70b4
   @verbatim
Packit 8f70b4
   double        ::= [ <sign> ]
Packit 8f70b4
                     ( <number> |
Packit 8f70b4
                       <number> <decimal_point> <number> |
Packit 8f70b4
                       <decimal_point> <number> )
Packit 8f70b4
                     [ <exponential> [ <sign> ] <number> ]
Packit 8f70b4
   number        ::= 1*( <digit> )
Packit 8f70b4
   digit         ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
Packit 8f70b4
   exponential   ::= ( 'e' | 'E' )
Packit 8f70b4
   sign          ::= ( '-' | '+' )
Packit 8f70b4
   decimal_point ::= '.'
Packit 8f70b4
   @endverbatim
Packit 8f70b4
*/
Packit 8f70b4
/* FIXME: Add EBNF for hex-floats */
Packit 8f70b4
TRIO_STRING_PUBLIC trio_long_double_t
Packit 8f70b4
trio_to_long_double
Packit 8f70b4
TRIO_ARGS2((source, endp),
Packit 8f70b4
	   TRIO_CONST char *source,
Packit 8f70b4
	   char **endp)
Packit 8f70b4
{
Packit 8f70b4
#if defined(USE_STRTOLD)
Packit 8f70b4
  return strtold(source, endp);
Packit 8f70b4
#else
Packit 8f70b4
  int isNegative = FALSE;
Packit 8f70b4
  int isExponentNegative = FALSE;
Packit 8f70b4
  trio_long_double_t integer = 0.0;
Packit 8f70b4
  trio_long_double_t fraction = 0.0;
Packit 8f70b4
  unsigned long exponent = 0;
Packit 8f70b4
  trio_long_double_t base;
Packit 8f70b4
  trio_long_double_t fracdiv = 1.0;
Packit 8f70b4
  trio_long_double_t value = 0.0;
Packit 8f70b4
Packit 8f70b4
  /* First try hex-floats */
Packit 8f70b4
  if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X')))
Packit 8f70b4
    {
Packit 8f70b4
      base = 16.0;
Packit 8f70b4
      source += 2;
Packit 8f70b4
      while (isxdigit((int)*source))
Packit 8f70b4
	{
Packit 8f70b4
	  integer *= base;
Packit 8f70b4
	  integer += (isdigit((int)*source)
Packit 8f70b4
		      ? (*source - '0')
Packit 8f70b4
		      : 10 + (toupper((int)*source) - 'A'));
Packit 8f70b4
	  source++;
Packit 8f70b4
	}
Packit 8f70b4
      if (*source == '.')
Packit 8f70b4
	{
Packit 8f70b4
	  source++;
Packit 8f70b4
	  while (isxdigit((int)*source))
Packit 8f70b4
	    {
Packit 8f70b4
	      fracdiv /= base;
Packit 8f70b4
	      fraction += fracdiv * (isdigit((int)*source)
Packit 8f70b4
				     ? (*source - '0')
Packit 8f70b4
				     : 10 + (toupper((int)*source) - 'A'));
Packit 8f70b4
	      source++;
Packit 8f70b4
	    }
Packit 8f70b4
	  if ((*source == 'p') || (*source == 'P'))
Packit 8f70b4
	    {
Packit 8f70b4
	      source++;
Packit 8f70b4
	      if ((*source == '+') || (*source == '-'))
Packit 8f70b4
		{
Packit 8f70b4
		  isExponentNegative = (*source == '-');
Packit 8f70b4
		  source++;
Packit 8f70b4
		}
Packit 8f70b4
	      while (isdigit((int)*source))
Packit 8f70b4
		{
Packit 8f70b4
		  exponent *= (int)base;
Packit 8f70b4
		  exponent += (*source - '0');
Packit 8f70b4
		  source++;
Packit 8f70b4
		}
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  else /* Then try normal decimal floats */
Packit 8f70b4
    {
Packit 8f70b4
      base = 10.0;
Packit 8f70b4
      isNegative = (*source == '-');
Packit 8f70b4
      /* Skip sign */
Packit 8f70b4
      if ((*source == '+') || (*source == '-'))
Packit 8f70b4
	source++;
Packit 8f70b4
Packit 8f70b4
      /* Integer part */
Packit 8f70b4
      while (isdigit((int)*source))
Packit 8f70b4
	{
Packit 8f70b4
	  integer *= base;
Packit 8f70b4
	  integer += (*source - '0');
Packit 8f70b4
	  source++;
Packit 8f70b4
	}
Packit 8f70b4
Packit 8f70b4
      if (*source == '.')
Packit 8f70b4
	{
Packit 8f70b4
	  source++; /* skip decimal point */
Packit 8f70b4
	  while (isdigit((int)*source))
Packit 8f70b4
	    {
Packit 8f70b4
	      fracdiv /= base;
Packit 8f70b4
	      fraction += (*source - '0') * fracdiv;
Packit 8f70b4
	      source++;
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
      if ((*source == 'e')
Packit 8f70b4
	  || (*source == 'E')
Packit 8f70b4
#if TRIO_MICROSOFT
Packit 8f70b4
	  || (*source == 'd')
Packit 8f70b4
	  || (*source == 'D')
Packit 8f70b4
#endif
Packit 8f70b4
	  )
Packit 8f70b4
	{
Packit 8f70b4
	  source++; /* Skip exponential indicator */
Packit 8f70b4
	  isExponentNegative = (*source == '-');
Packit 8f70b4
	  if ((*source == '+') || (*source == '-'))
Packit 8f70b4
	    source++;
Packit 8f70b4
	  while (isdigit((int)*source))
Packit 8f70b4
	    {
Packit 8f70b4
	      exponent *= (int)base;
Packit 8f70b4
	      exponent += (*source - '0');
Packit 8f70b4
	      source++;
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  
Packit 8f70b4
  value = integer + fraction;
Packit 8f70b4
  if (exponent != 0)
Packit 8f70b4
    {
Packit 8f70b4
      if (isExponentNegative)
Packit 8f70b4
	value /= pow(base, (double)exponent);
Packit 8f70b4
      else
Packit 8f70b4
	value *= pow(base, (double)exponent);
Packit 8f70b4
    }
Packit 8f70b4
  if (isNegative)
Packit 8f70b4
    value = -value;
Packit 8f70b4
Packit 8f70b4
  if (endp)
Packit 8f70b4
    *endp = (char *)source;
Packit 8f70b4
  return value;
Packit 8f70b4
#endif
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Convert string to floating-point number.
Packit 8f70b4
Packit 8f70b4
   @param source String to be converted.
Packit 8f70b4
   @param endp Pointer to end of the converted string.
Packit 8f70b4
   @return A floating-point number.
Packit 8f70b4
Packit 8f70b4
   See @ref trio_to_long_double.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC double
Packit 8f70b4
trio_to_double
Packit 8f70b4
TRIO_ARGS2((source, endp),
Packit 8f70b4
	   TRIO_CONST char *source,
Packit 8f70b4
	   char **endp)
Packit 8f70b4
{
Packit 8f70b4
#if defined(USE_STRTOD)
Packit 8f70b4
  return strtod(source, endp);
Packit 8f70b4
#else
Packit 8f70b4
  return (double)trio_to_long_double(source, endp);
Packit 8f70b4
#endif
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Convert string to floating-point number.
Packit 8f70b4
Packit 8f70b4
   @param source String to be converted.
Packit 8f70b4
   @param endp Pointer to end of the converted string.
Packit 8f70b4
   @return A floating-point number.
Packit 8f70b4
Packit 8f70b4
   See @ref trio_to_long_double.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC float
Packit 8f70b4
trio_to_float
Packit 8f70b4
TRIO_ARGS2((source, endp),
Packit 8f70b4
	   TRIO_CONST char *source,
Packit 8f70b4
	   char **endp)
Packit 8f70b4
{
Packit 8f70b4
#if defined(USE_STRTOF)
Packit 8f70b4
  return strtof(source, endp);
Packit 8f70b4
#else
Packit 8f70b4
  return (float)trio_to_long_double(source, endp);
Packit 8f70b4
#endif
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Convert string to signed integer.
Packit 8f70b4
Packit 8f70b4
   @param string String to be converted.
Packit 8f70b4
   @param endp Pointer to end of converted string.
Packit 8f70b4
   @param base Radix number of number.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC long
Packit 8f70b4
trio_to_long
Packit 8f70b4
TRIO_ARGS3((string, endp, base),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   char **endp,
Packit 8f70b4
	   int base)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert((base >= 2) && (base <= 36));
Packit 8f70b4
  
Packit 8f70b4
  return strtol(string, endp, base);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Convert string to unsigned integer.
Packit 8f70b4
Packit 8f70b4
   @param string String to be converted.
Packit 8f70b4
   @param endp Pointer to end of converted string.
Packit 8f70b4
   @param base Radix number of number.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC unsigned long
Packit 8f70b4
trio_to_unsigned_long
Packit 8f70b4
TRIO_ARGS3((string, endp, base),
Packit 8f70b4
	   TRIO_CONST char *string,
Packit 8f70b4
	   char **endp,
Packit 8f70b4
	   int base)
Packit 8f70b4
{
Packit 8f70b4
  assert(string);
Packit 8f70b4
  assert((base >= 2) && (base <= 36));
Packit 8f70b4
  
Packit 8f70b4
  return strtoul(string, endp, base);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Convert the alphabetic letters in the string to upper-case.
Packit 8f70b4
Packit 8f70b4
   @param target The string to be converted.
Packit 8f70b4
   @return The number of processed characters (converted or not).
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_upper
Packit 8f70b4
TRIO_ARGS1((target),
Packit 8f70b4
	   char *target)
Packit 8f70b4
{
Packit 8f70b4
  assert(target);
Packit 8f70b4
Packit 8f70b4
  return trio_span_function(target, target, toupper);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/** @} End of StaticStrings */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*************************************************************************
Packit 8f70b4
 * Dynamic String Functions
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#if defined(TRIO_DOCUMENTATION)
Packit 8f70b4
# include "doc/doc_dynamic.h"
Packit 8f70b4
#endif
Packit 8f70b4
/** @addtogroup DynamicStrings
Packit 8f70b4
    @{
Packit 8f70b4
*/
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * TrioStringAlloc
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PRIVATE trio_string_t *
Packit 8f70b4
TrioStringAlloc(TRIO_NOARGS)
Packit 8f70b4
{
Packit 8f70b4
  trio_string_t *self;
Packit 8f70b4
  
Packit 8f70b4
  self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t));
Packit 8f70b4
  if (self)
Packit 8f70b4
    {
Packit 8f70b4
      self->content = NULL;
Packit 8f70b4
      self->length = 0;
Packit 8f70b4
      self->allocated = 0;
Packit 8f70b4
    }
Packit 8f70b4
  return self;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * TrioStringGrow
Packit 8f70b4
 *
Packit 8f70b4
 * The size of the string will be increased by 'delta' characters. If
Packit 8f70b4
 * 'delta' is zero, the size will be doubled.
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PRIVATE BOOLEAN_T
Packit 8f70b4
TrioStringGrow
Packit 8f70b4
TRIO_ARGS2((self, delta),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t delta)
Packit 8f70b4
{
Packit 8f70b4
  BOOLEAN_T status = FALSE;
Packit 8f70b4
  char *new_content;
Packit 8f70b4
  size_t new_size;
Packit 8f70b4
Packit 8f70b4
  new_size = (delta == 0)
Packit 8f70b4
    ? ( (self->allocated == 0) ? 1 : self->allocated * 2 )
Packit 8f70b4
    : self->allocated + delta;
Packit 8f70b4
  
Packit 8f70b4
  new_content = (char *)TRIO_REALLOC(self->content, new_size);
Packit 8f70b4
  if (new_content)
Packit 8f70b4
    {
Packit 8f70b4
      self->content = new_content;
Packit 8f70b4
      self->allocated = new_size;
Packit 8f70b4
      status = TRUE;
Packit 8f70b4
    }
Packit 8f70b4
  return status;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * TrioStringGrowTo
Packit 8f70b4
 *
Packit 8f70b4
 * The size of the string will be increased to 'length' plus one characters.
Packit 8f70b4
 * If 'length' is less than the original size, the original size will be
Packit 8f70b4
 * used (that is, the size of the string is never decreased).
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PRIVATE BOOLEAN_T
Packit 8f70b4
TrioStringGrowTo
Packit 8f70b4
TRIO_ARGS2((self, length),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t length)
Packit 8f70b4
{
Packit 8f70b4
  length++; /* Room for terminating zero */
Packit 8f70b4
  return (self->allocated < length)
Packit 8f70b4
    ? TrioStringGrow(self, length - self->allocated)
Packit 8f70b4
    : TRUE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Create a new dynamic string.
Packit 8f70b4
   
Packit 8f70b4
   @param initial_size Initial size of the buffer.
Packit 8f70b4
   @return Newly allocated dynamic string, or NULL if memory allocation failed.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC trio_string_t *
Packit 8f70b4
trio_string_create
Packit 8f70b4
TRIO_ARGS1((initial_size),
Packit 8f70b4
	   int initial_size)
Packit 8f70b4
{
Packit 8f70b4
  trio_string_t *self;
Packit 8f70b4
Packit 8f70b4
  self = TrioStringAlloc();
Packit 8f70b4
  if (self)
Packit 8f70b4
    {
Packit 8f70b4
      if (TrioStringGrow(self,
Packit 8f70b4
			 (size_t)((initial_size > 0) ? initial_size : 1)))
Packit 8f70b4
	{
Packit 8f70b4
	  self->content[0] = (char)0;
Packit 8f70b4
	  self->allocated = initial_size;
Packit 8f70b4
	}
Packit 8f70b4
      else
Packit 8f70b4
	{
Packit 8f70b4
	  trio_string_destroy(self);
Packit 8f70b4
	  self = NULL;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  return self;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Deallocate the dynamic string and its contents.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic string
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC void
Packit 8f70b4
trio_string_destroy
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  
Packit 8f70b4
  if (self)
Packit 8f70b4
    {
Packit 8f70b4
      trio_destroy(self->content);
Packit 8f70b4
      TRIO_FREE(self);
Packit 8f70b4
    }
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Get a pointer to the content.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic string.
Packit 8f70b4
   @param offset Offset into content.
Packit 8f70b4
   @return Pointer to the content.
Packit 8f70b4
   
Packit 8f70b4
   @p Offset can be zero, positive, or negative. If @p offset is zero,
Packit 8f70b4
   then the start of the content will be returned. If @p offset is positive,
Packit 8f70b4
   then a pointer to @p offset number of characters from the beginning of the
Packit 8f70b4
   content is returned. If @p offset is negative, then a pointer to @p offset
Packit 8f70b4
   number of characters from the ending of the string, starting at the
Packit 8f70b4
   terminating zero, is returned.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_string_get
Packit 8f70b4
TRIO_ARGS2((self, offset),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   int offset)
Packit 8f70b4
{
Packit 8f70b4
  char *result = NULL;
Packit 8f70b4
  
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  if (self->content != NULL)
Packit 8f70b4
    {
Packit 8f70b4
      if (self->length == 0)
Packit 8f70b4
	{
Packit 8f70b4
	  (void)trio_string_length(self);
Packit 8f70b4
	}
Packit 8f70b4
      if (offset >= 0)
Packit 8f70b4
	{
Packit 8f70b4
	  if (offset > (int)self->length)
Packit 8f70b4
	    {
Packit 8f70b4
	      offset = self->length;
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
      else
Packit 8f70b4
	{
Packit 8f70b4
	  offset += self->length + 1;
Packit 8f70b4
	  if (offset < 0)
Packit 8f70b4
	    {
Packit 8f70b4
	      offset = 0;
Packit 8f70b4
	    }
Packit 8f70b4
	}
Packit 8f70b4
      result = &(self->content[offset]);
Packit 8f70b4
    }
Packit 8f70b4
  return result;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/**
Packit 8f70b4
   Extract the content.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic String
Packit 8f70b4
   @return Content of dynamic string.
Packit 8f70b4
   
Packit 8f70b4
   The content is removed from the dynamic string. This enables destruction
Packit 8f70b4
   of the dynamic string without deallocation of the content.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_string_extract
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  char *result;
Packit 8f70b4
  
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  result = self->content;
Packit 8f70b4
  /* FIXME: Allocate new empty buffer? */
Packit 8f70b4
  self->content = NULL;
Packit 8f70b4
  self->length = self->allocated = 0;
Packit 8f70b4
  return result;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Set the content of the dynamic string.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic String
Packit 8f70b4
   @param buffer The new content.
Packit 8f70b4
   
Packit 8f70b4
   Sets the content of the dynamic string to a copy @p buffer.
Packit 8f70b4
   An existing content will be deallocated first, if necessary.
Packit 8f70b4
   
Packit 8f70b4
   @remark
Packit 8f70b4
   This function will make a copy of @p buffer.
Packit 8f70b4
   You are responsible for deallocating @p buffer yourself.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC void
Packit 8f70b4
trio_xstring_set
Packit 8f70b4
TRIO_ARGS2((self, buffer),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   char *buffer)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  trio_destroy(self->content);
Packit 8f70b4
  self->content = trio_duplicate(buffer);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_size
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_size
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return self->allocated;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_terminate
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC void
Packit 8f70b4
trio_string_terminate
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  trio_xstring_append_char(self, 0);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Append the second string to the first.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic string to be modified.
Packit 8f70b4
   @param other Dynamic string to copy from.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_append
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  size_t length;
Packit 8f70b4
  
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  length = self->length + other->length;
Packit 8f70b4
  if (!TrioStringGrowTo(self, length))
Packit 8f70b4
    goto error;
Packit 8f70b4
  trio_copy(&self->content[self->length], other->content);
Packit 8f70b4
  self->length = length;
Packit 8f70b4
  return TRUE;
Packit 8f70b4
  
Packit 8f70b4
 error:
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_append
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_append
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  size_t length;
Packit 8f70b4
  
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  length = self->length + trio_length(other);
Packit 8f70b4
  if (!TrioStringGrowTo(self, length))
Packit 8f70b4
    goto error;
Packit 8f70b4
  trio_copy(&self->content[self->length], other);
Packit 8f70b4
  self->length = length;
Packit 8f70b4
  return TRUE;
Packit 8f70b4
  
Packit 8f70b4
 error:
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_append_char
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_append_char
Packit 8f70b4
TRIO_ARGS2((self, character),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   char character)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  if ((int)self->length >= trio_string_size(self))
Packit 8f70b4
    {
Packit 8f70b4
      if (!TrioStringGrow(self, 0))
Packit 8f70b4
	goto error;
Packit 8f70b4
    }
Packit 8f70b4
  self->content[self->length] = character;
Packit 8f70b4
  self->length++;
Packit 8f70b4
  return TRUE;
Packit 8f70b4
  
Packit 8f70b4
 error:
Packit 8f70b4
  return FALSE;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/**
Packit 8f70b4
   Search for the first occurrence of second parameter in the first.
Packit 8f70b4
   
Packit 8f70b4
   @param self Dynamic string to be modified.
Packit 8f70b4
   @param other Dynamic string to copy from.
Packit 8f70b4
   @return Boolean value indicating success or failure.
Packit 8f70b4
*/
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_contains
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_contains(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_contains
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_contains
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_contains(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_copy
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_copy
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  self->length = 0;
Packit 8f70b4
  return trio_string_append(self, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_copy
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_copy
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  self->length = 0;
Packit 8f70b4
  return trio_xstring_append(self, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_duplicate
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC trio_string_t *
Packit 8f70b4
trio_string_duplicate
Packit 8f70b4
TRIO_ARGS1((other),
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  trio_string_t *self;
Packit 8f70b4
  
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  self = TrioStringAlloc();
Packit 8f70b4
  if (self)
Packit 8f70b4
    {
Packit 8f70b4
      self->content = TrioDuplicateMax(other->content, other->length);
Packit 8f70b4
      if (self->content)
Packit 8f70b4
	{
Packit 8f70b4
	  self->length = other->length;
Packit 8f70b4
	  self->allocated = self->length + 1;
Packit 8f70b4
	}
Packit 8f70b4
      else
Packit 8f70b4
	{
Packit 8f70b4
	  self->length = self->allocated = 0;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  return self;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_duplicate
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC trio_string_t *
Packit 8f70b4
trio_xstring_duplicate
Packit 8f70b4
TRIO_ARGS1((other),
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  trio_string_t *self;
Packit 8f70b4
  
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  self = TrioStringAlloc();
Packit 8f70b4
  if (self)
Packit 8f70b4
    {
Packit 8f70b4
      self->content = TrioDuplicateMax(other, trio_length(other));
Packit 8f70b4
      if (self->content)
Packit 8f70b4
	{
Packit 8f70b4
	  self->length = trio_length(self->content);
Packit 8f70b4
	  self->allocated = self->length + 1;
Packit 8f70b4
	}
Packit 8f70b4
      else
Packit 8f70b4
	{
Packit 8f70b4
	  self->length = self->allocated = 0;
Packit 8f70b4
	}
Packit 8f70b4
    }
Packit 8f70b4
  return self;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_equal
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_equal
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_equal
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_equal
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_equal_max
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_equal_max
Packit 8f70b4
TRIO_ARGS3((self, max, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_max(self->content, max, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_equal_max
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_equal_max
Packit 8f70b4
TRIO_ARGS3((self, max, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_max(self->content, max, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_equal_case
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_equal_case
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_case(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_equal_case
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_equal_case
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_case(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_equal_case_max
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_equal_case_max
Packit 8f70b4
TRIO_ARGS3((self, max, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_case_max(self->content, max, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_equal_case_max
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_equal_case_max
Packit 8f70b4
TRIO_ARGS3((self, max, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_equal_case_max(self->content, max, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_format_data_max
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC size_t
Packit 8f70b4
trio_string_format_date_max
Packit 8f70b4
TRIO_ARGS4((self, max, format, datetime),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   size_t max,
Packit 8f70b4
	   TRIO_CONST char *format,
Packit 8f70b4
	   TRIO_CONST struct tm *datetime)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return trio_format_date_max(self->content, max, format, datetime);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_index
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_string_index
Packit 8f70b4
TRIO_ARGS2((self, character),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   int character)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return trio_index(self->content, character);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_index_last
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_string_index_last
Packit 8f70b4
TRIO_ARGS2((self, character),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   int character)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return trio_index_last(self->content, character);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_length
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_length
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  if (self->length == 0)
Packit 8f70b4
    {
Packit 8f70b4
      self->length = trio_length(self->content);
Packit 8f70b4
    }
Packit 8f70b4
  return self->length;
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_lower
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_lower
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return trio_lower(self->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_match
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_match
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_match(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_match
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_match
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_match(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_match_case
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_match_case
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_match_case(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_match_case
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_xstring_match_case
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_match_case(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_substring
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_string_substring
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   trio_string_t *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_substring(self->content, other->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_xstring_substring
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC char *
Packit 8f70b4
trio_xstring_substring
Packit 8f70b4
TRIO_ARGS2((self, other),
Packit 8f70b4
	   trio_string_t *self,
Packit 8f70b4
	   TRIO_CONST char *other)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
  assert(other);
Packit 8f70b4
Packit 8f70b4
  return trio_substring(self->content, other);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#if !defined(TRIO_MINIMAL)
Packit 8f70b4
/*
Packit 8f70b4
 * trio_string_upper
Packit 8f70b4
 */
Packit 8f70b4
TRIO_STRING_PUBLIC int
Packit 8f70b4
trio_string_upper
Packit 8f70b4
TRIO_ARGS1((self),
Packit 8f70b4
	   trio_string_t *self)
Packit 8f70b4
{
Packit 8f70b4
  assert(self);
Packit 8f70b4
Packit 8f70b4
  return trio_upper(self->content);
Packit 8f70b4
}
Packit 8f70b4
#endif /* !defined(TRIO_MINIMAL) */
Packit 8f70b4
Packit 8f70b4
/** @} End of DynamicStrings */