Blame triostr.c

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