Annotation of embedaddon/libxml2/triostr.c, revision 1.1

1.1     ! misho       1: /*************************************************************************
        !             2:  *
        !             3:  * $Id$
        !             4:  *
        !             5:  * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            12:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            13:  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
        !            14:  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
        !            15:  *
        !            16:  ************************************************************************/
        !            17: 
        !            18: /*************************************************************************
        !            19:  * Include files
        !            20:  */
        !            21: 
        !            22: #include <assert.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include <ctype.h>
        !            26: #include <math.h>
        !            27: #include "triodef.h"
        !            28: #include "triostr.h"
        !            29: 
        !            30: /*************************************************************************
        !            31:  * Definitions
        !            32:  */
        !            33: 
        !            34: #if !defined(TRIO_STRING_PUBLIC)
        !            35: # define TRIO_STRING_PUBLIC TRIO_PUBLIC
        !            36: #endif
        !            37: #if !defined(TRIO_STRING_PRIVATE)
        !            38: # define TRIO_STRING_PRIVATE TRIO_PRIVATE
        !            39: #endif
        !            40: 
        !            41: #if !defined(NULL)
        !            42: # define NULL 0
        !            43: #endif
        !            44: #if !defined(NIL)
        !            45: # define NIL ((char)0)
        !            46: #endif
        !            47: #if !defined(FALSE)
        !            48: # define FALSE (1 == 0)
        !            49: # define TRUE (! FALSE)
        !            50: #endif
        !            51: #if !defined(BOOLEAN_T)
        !            52: # define BOOLEAN_T int
        !            53: #endif
        !            54: 
        !            55: #if defined(TRIO_COMPILER_SUPPORTS_C99)
        !            56: # define USE_STRTOD
        !            57: # define USE_STRTOF
        !            58: #elif defined(TRIO_COMPILER_MSVC)
        !            59: # define USE_STRTOD
        !            60: #endif
        !            61: 
        !            62: #if defined(TRIO_PLATFORM_UNIX)
        !            63: # define USE_STRCASECMP
        !            64: # define USE_STRNCASECMP
        !            65: # if defined(TRIO_PLATFORM_SUNOS)
        !            66: #  define USE_SYS_ERRLIST
        !            67: # else
        !            68: #  define USE_STRERROR
        !            69: # endif
        !            70: # if defined(TRIO_PLATFORM_QNX)
        !            71: #  define strcasecmp(x,y) stricmp(x,y)
        !            72: #  define strncasecmp(x,y,n) strnicmp(x,y,n)
        !            73: # endif
        !            74: #elif defined(TRIO_PLATFORM_WIN32)
        !            75: # define USE_STRCASECMP
        !            76: # if defined(_WIN32_WCE)
        !            77: #  define strcasecmp(x,y) _stricmp(x,y)
        !            78: # else
        !            79: #  define strcasecmp(x,y) strcmpi(x,y)
        !            80: # endif
        !            81: #endif
        !            82: 
        !            83: #if !(defined(TRIO_PLATFORM_SUNOS))
        !            84: # define USE_TOLOWER
        !            85: # define USE_TOUPPER
        !            86: #endif
        !            87: 
        !            88: /*************************************************************************
        !            89:  * Structures
        !            90:  */
        !            91: 
        !            92: struct _trio_string_t
        !            93: {
        !            94:   char *content;
        !            95:   size_t length;
        !            96:   size_t allocated;
        !            97: };
        !            98: 
        !            99: /*************************************************************************
        !           100:  * Constants
        !           101:  */
        !           102: 
        !           103: #if !defined(TRIO_MINIMAL)
        !           104: static TRIO_CONST char rcsid[] = "@(#)$Id$";
        !           105: #endif
        !           106: 
        !           107: /*************************************************************************
        !           108:  * Static String Functions
        !           109:  */
        !           110: 
        !           111: #if defined(TRIO_DOCUMENTATION)
        !           112: # include "doc/doc_static.h"
        !           113: #endif
        !           114: /** @addtogroup StaticStrings
        !           115:     @{
        !           116: */
        !           117: 
        !           118: /**
        !           119:    Create new string.
        !           120: 
        !           121:    @param size Size of new string.
        !           122:    @return Pointer to string, or NULL if allocation failed.
        !           123: */
        !           124: TRIO_STRING_PUBLIC char *
        !           125: trio_create
        !           126: TRIO_ARGS1((size),
        !           127:           size_t size)
        !           128: {
        !           129:   return (char *)TRIO_MALLOC(size);
        !           130: }
        !           131: 
        !           132: 
        !           133: /**
        !           134:    Destroy string.
        !           135: 
        !           136:    @param string String to be freed.
        !           137: */
        !           138: TRIO_STRING_PUBLIC void
        !           139: trio_destroy
        !           140: TRIO_ARGS1((string),
        !           141:           char *string)
        !           142: {
        !           143:   if (string)
        !           144:     {
        !           145:       TRIO_FREE(string);
        !           146:     }
        !           147: }
        !           148: 
        !           149: 
        !           150: /**
        !           151:    Count the number of characters in a string.
        !           152: 
        !           153:    @param string String to measure.
        !           154:    @return Number of characters in @string.
        !           155: */
        !           156: TRIO_STRING_PUBLIC size_t
        !           157: trio_length
        !           158: TRIO_ARGS1((string),
        !           159:           TRIO_CONST char *string)
        !           160: {
        !           161:   return strlen(string);
        !           162: }
        !           163: 
        !           164: 
        !           165: #if !defined(TRIO_MINIMAL)
        !           166: /**
        !           167:    Append @p source at the end of @p target.
        !           168:    
        !           169:    @param target Target string.
        !           170:    @param source Source string.
        !           171:    @return Boolean value indicating success or failure.
        !           172:    
        !           173:    @pre @p target must point to a memory chunk with sufficient room to
        !           174:    contain the @p target string and @p source string.
        !           175:    @pre No boundary checking is performed, so insufficient memory will
        !           176:    result in a buffer overrun.
        !           177:    @post @p target will be zero terminated.
        !           178: */
        !           179: TRIO_STRING_PUBLIC int
        !           180: trio_append
        !           181: TRIO_ARGS2((target, source),
        !           182:           char *target,
        !           183:           TRIO_CONST char *source)
        !           184: {
        !           185:   assert(target);
        !           186:   assert(source);
        !           187:   
        !           188:   return (strcat(target, source) != NULL);
        !           189: }
        !           190: #endif /* !defined(TRIO_MINIMAL) */
        !           191: 
        !           192: #if !defined(TRIO_MINIMAL)
        !           193: /**
        !           194:    Append at most @p max characters from @p source to @p target.
        !           195:    
        !           196:    @param target Target string.
        !           197:    @param max Maximum number of characters to append.
        !           198:    @param source Source string.
        !           199:    @return Boolean value indicating success or failure.
        !           200:    
        !           201:    @pre @p target must point to a memory chuck with sufficient room to
        !           202:    contain the @p target string and the @p source string (at most @p max
        !           203:    characters).
        !           204:    @pre No boundary checking is performed, so insufficient memory will
        !           205:    result in a buffer overrun.
        !           206:    @post @p target will be zero terminated.
        !           207: */
        !           208: TRIO_STRING_PUBLIC int
        !           209: trio_append_max
        !           210: TRIO_ARGS3((target, max, source),
        !           211:           char *target,
        !           212:           size_t max,
        !           213:           TRIO_CONST char *source)
        !           214: {
        !           215:   size_t length;
        !           216:   
        !           217:   assert(target);
        !           218:   assert(source);
        !           219: 
        !           220:   length = trio_length(target);
        !           221:   
        !           222:   if (max > length)
        !           223:     {
        !           224:       strncat(target, source, max - length - 1);
        !           225:     }
        !           226:   return TRUE;
        !           227: }
        !           228: #endif /* !defined(TRIO_MINIMAL) */
        !           229: 
        !           230: 
        !           231: #if !defined(TRIO_MINIMAL)
        !           232: /**
        !           233:    Determine if a string contains a substring.
        !           234: 
        !           235:    @param string String to be searched.
        !           236:    @param substring String to be found.
        !           237:    @return Boolean value indicating success or failure.
        !           238: */
        !           239: TRIO_STRING_PUBLIC int
        !           240: trio_contains
        !           241: TRIO_ARGS2((string, substring),
        !           242:           TRIO_CONST char *string,
        !           243:           TRIO_CONST char *substring)
        !           244: {
        !           245:   assert(string);
        !           246:   assert(substring);
        !           247:   
        !           248:   return (0 != strstr(string, substring));
        !           249: }
        !           250: #endif /* !defined(TRIO_MINIMAL) */
        !           251: 
        !           252: 
        !           253: #if !defined(TRIO_MINIMAL)
        !           254: /**
        !           255:    Copy @p source to @p target.
        !           256:    
        !           257:    @param target Target string.
        !           258:    @param source Source string.
        !           259:    @return Boolean value indicating success or failure.
        !           260:    
        !           261:    @pre @p target must point to a memory chunk with sufficient room to
        !           262:    contain the @p source string.
        !           263:    @pre No boundary checking is performed, so insufficient memory will
        !           264:    result in a buffer overrun.
        !           265:    @post @p target will be zero terminated.
        !           266: */
        !           267: TRIO_STRING_PUBLIC int
        !           268: trio_copy
        !           269: TRIO_ARGS2((target, source),
        !           270:           char *target,
        !           271:           TRIO_CONST char *source)
        !           272: {
        !           273:   assert(target);
        !           274:   assert(source);
        !           275:      
        !           276:   (void)strcpy(target, source);
        !           277:   return TRUE;
        !           278: }
        !           279: #endif /* !defined(TRIO_MINIMAL) */
        !           280: 
        !           281: 
        !           282: /**
        !           283:    Copy at most @p max characters from @p source to @p target.
        !           284:    
        !           285:    @param target Target string.
        !           286:    @param max Maximum number of characters to append.
        !           287:    @param source Source string.
        !           288:    @return Boolean value indicating success or failure.
        !           289:    
        !           290:    @pre @p target must point to a memory chunk with sufficient room to
        !           291:    contain the @p source string (at most @p max characters).
        !           292:    @pre No boundary checking is performed, so insufficient memory will
        !           293:    result in a buffer overrun.
        !           294:    @post @p target will be zero terminated.
        !           295: */
        !           296: TRIO_STRING_PUBLIC int
        !           297: trio_copy_max
        !           298: TRIO_ARGS3((target, max, source),
        !           299:           char *target,
        !           300:           size_t max,
        !           301:           TRIO_CONST char *source)
        !           302: {
        !           303:   assert(target);
        !           304:   assert(source);
        !           305:   assert(max > 0); /* Includes != 0 */
        !           306: 
        !           307:   (void)strncpy(target, source, max - 1);
        !           308:   target[max - 1] = (char)0;
        !           309:   return TRUE;
        !           310: }
        !           311: 
        !           312: 
        !           313: /*
        !           314:  * TrioDuplicateMax
        !           315:  */
        !           316: TRIO_STRING_PRIVATE char *
        !           317: TrioDuplicateMax
        !           318: TRIO_ARGS2((source, size),
        !           319:           TRIO_CONST char *source,
        !           320:           size_t size)
        !           321: {
        !           322:   char *target;
        !           323: 
        !           324:   assert(source);
        !           325: 
        !           326:   /* Make room for string plus a terminating zero */
        !           327:   size++;
        !           328:   target = trio_create(size);
        !           329:   if (target)
        !           330:     {
        !           331:       trio_copy_max(target, size, source);
        !           332:     }
        !           333:   return target;
        !           334: }
        !           335: 
        !           336: 
        !           337: /**
        !           338:    Duplicate @p source.
        !           339:    
        !           340:    @param source Source string.
        !           341:    @return A copy of the @p source string.
        !           342:    
        !           343:    @post @p target will be zero terminated.
        !           344: */
        !           345: TRIO_STRING_PUBLIC char *
        !           346: trio_duplicate
        !           347: TRIO_ARGS1((source),
        !           348:           TRIO_CONST char *source)
        !           349: {
        !           350:   return TrioDuplicateMax(source, trio_length(source));
        !           351: }
        !           352: 
        !           353: 
        !           354: #if !defined(TRIO_MINIMAL)
        !           355: /**
        !           356:    Duplicate at most @p max characters of @p source.
        !           357:    
        !           358:    @param source Source string.
        !           359:    @param max Maximum number of characters to duplicate.
        !           360:    @return A copy of the @p source string.
        !           361:    
        !           362:    @post @p target will be zero terminated.
        !           363: */
        !           364: TRIO_STRING_PUBLIC char *
        !           365: trio_duplicate_max TRIO_ARGS2((source, max),
        !           366:                              TRIO_CONST char *source,
        !           367:                              size_t max)
        !           368: {
        !           369:   size_t length;
        !           370: 
        !           371:   assert(source);
        !           372:   assert(max > 0);
        !           373: 
        !           374:   length = trio_length(source);
        !           375:   if (length > max)
        !           376:     {
        !           377:       length = max;
        !           378:     }
        !           379:   return TrioDuplicateMax(source, length);
        !           380: }
        !           381: #endif /* !defined(TRIO_MINIMAL) */
        !           382: 
        !           383: 
        !           384: /**
        !           385:    Compare if two strings are equal.
        !           386:    
        !           387:    @param first First string.
        !           388:    @param second Second string.
        !           389:    @return Boolean indicating whether the two strings are equal or not.
        !           390:    
        !           391:    Case-insensitive comparison.
        !           392: */
        !           393: TRIO_STRING_PUBLIC int
        !           394: trio_equal
        !           395: TRIO_ARGS2((first, second),
        !           396:           TRIO_CONST char *first,
        !           397:           TRIO_CONST char *second)
        !           398: {
        !           399:   assert(first);
        !           400:   assert(second);
        !           401: 
        !           402:   if ((first != NULL) && (second != NULL))
        !           403:     {
        !           404: #if defined(USE_STRCASECMP)
        !           405:       return (0 == strcasecmp(first, second));
        !           406: #else
        !           407:       while ((*first != NIL) && (*second != NIL))
        !           408:        {
        !           409:          if (trio_to_upper(*first) != trio_to_upper(*second))
        !           410:            {
        !           411:              break;
        !           412:            }
        !           413:          first++;
        !           414:          second++;
        !           415:        }
        !           416:       return ((*first == NIL) && (*second == NIL));
        !           417: #endif
        !           418:     }
        !           419:   return FALSE;
        !           420: }
        !           421: 
        !           422: 
        !           423: /**
        !           424:    Compare if two strings are equal.
        !           425:    
        !           426:    @param first First string.
        !           427:    @param second Second string.
        !           428:    @return Boolean indicating whether the two strings are equal or not.
        !           429:    
        !           430:    Case-sensitive comparison.
        !           431: */
        !           432: TRIO_STRING_PUBLIC int
        !           433: trio_equal_case
        !           434: TRIO_ARGS2((first, second),
        !           435:           TRIO_CONST char *first,
        !           436:           TRIO_CONST char *second)
        !           437: {
        !           438:   assert(first);
        !           439:   assert(second);
        !           440: 
        !           441:   if ((first != NULL) && (second != NULL))
        !           442:     {
        !           443:       return (0 == strcmp(first, second));
        !           444:     }
        !           445:   return FALSE;
        !           446: }
        !           447: 
        !           448: 
        !           449: #if !defined(TRIO_MINIMAL)
        !           450: /**
        !           451:    Compare if two strings up until the first @p max characters are equal.
        !           452:    
        !           453:    @param first First string.
        !           454:    @param max Maximum number of characters to compare.
        !           455:    @param second Second string.
        !           456:    @return Boolean indicating whether the two strings are equal or not.
        !           457:    
        !           458:    Case-sensitive comparison.
        !           459: */
        !           460: TRIO_STRING_PUBLIC int
        !           461: trio_equal_case_max
        !           462: TRIO_ARGS3((first, max, second),
        !           463:           TRIO_CONST char *first,
        !           464:           size_t max,
        !           465:           TRIO_CONST char *second)
        !           466: {
        !           467:   assert(first);
        !           468:   assert(second);
        !           469: 
        !           470:   if ((first != NULL) && (second != NULL))
        !           471:     {
        !           472:       return (0 == strncmp(first, second, max));
        !           473:     }
        !           474:   return FALSE;
        !           475: }
        !           476: #endif /* !defined(TRIO_MINIMAL) */
        !           477: 
        !           478: 
        !           479: /**
        !           480:    Compare if two strings are equal.
        !           481:    
        !           482:    @param first First string.
        !           483:    @param second Second string.
        !           484:    @return Boolean indicating whether the two strings are equal or not.
        !           485: 
        !           486:    Collating characters are considered equal.
        !           487: */
        !           488: TRIO_STRING_PUBLIC int
        !           489: trio_equal_locale
        !           490: TRIO_ARGS2((first, second),
        !           491:           TRIO_CONST char *first,
        !           492:           TRIO_CONST char *second)
        !           493: {
        !           494:   assert(first);
        !           495:   assert(second);
        !           496: 
        !           497: #if defined(LC_COLLATE)
        !           498:   return (strcoll(first, second) == 0);
        !           499: #else
        !           500:   return trio_equal(first, second);
        !           501: #endif
        !           502: }
        !           503: 
        !           504: 
        !           505: /**
        !           506:    Compare if two strings up until the first @p max characters are equal.
        !           507:    
        !           508:    @param first First string.
        !           509:    @param max Maximum number of characters to compare.
        !           510:    @param second Second string.
        !           511:    @return Boolean indicating whether the two strings are equal or not.
        !           512:    
        !           513:    Case-insensitive comparison.
        !           514: */
        !           515: TRIO_STRING_PUBLIC int
        !           516: trio_equal_max
        !           517: TRIO_ARGS3((first, max, second),
        !           518:           TRIO_CONST char *first,
        !           519:           size_t max,
        !           520:           TRIO_CONST char *second)
        !           521: {
        !           522:   assert(first);
        !           523:   assert(second);
        !           524: 
        !           525:   if ((first != NULL) && (second != NULL))
        !           526:     {
        !           527: #if defined(USE_STRNCASECMP)
        !           528:       return (0 == strncasecmp(first, second, max));
        !           529: #else
        !           530:       /* Not adequately tested yet */
        !           531:       size_t cnt = 0;
        !           532:       while ((*first != NIL) && (*second != NIL) && (cnt <= max))
        !           533:        {
        !           534:          if (trio_to_upper(*first) != trio_to_upper(*second))
        !           535:            {
        !           536:              break;
        !           537:            }
        !           538:          first++;
        !           539:          second++;
        !           540:          cnt++;
        !           541:        }
        !           542:       return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
        !           543: #endif
        !           544:     }
        !           545:   return FALSE;
        !           546: }
        !           547: 
        !           548: 
        !           549: /**
        !           550:    Provide a textual description of an error code (errno).
        !           551: 
        !           552:    @param error_number Error number.
        !           553:    @return Textual description of @p error_number.
        !           554: */
        !           555: TRIO_STRING_PUBLIC TRIO_CONST char *
        !           556: trio_error
        !           557: TRIO_ARGS1((error_number),
        !           558:           int error_number)
        !           559: {
        !           560: #if defined(USE_STRERROR)
        !           561:   
        !           562:   return strerror(error_number);
        !           563: 
        !           564: #elif defined(USE_SYS_ERRLIST)
        !           565: 
        !           566:   extern char *sys_errlist[];
        !           567:   extern int sys_nerr;
        !           568: 
        !           569:   return ((error_number < 0) || (error_number >= sys_nerr))
        !           570:     ? "unknown"
        !           571:     : sys_errlist[error_number];
        !           572:  
        !           573: #else
        !           574:   
        !           575:   return "unknown";
        !           576:   
        !           577: #endif
        !           578: }
        !           579: 
        !           580: 
        !           581: #if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE)
        !           582: /**
        !           583:    Format the date/time according to @p format.
        !           584: 
        !           585:    @param target Target string.
        !           586:    @param max Maximum number of characters to format.
        !           587:    @param format Formatting string.
        !           588:    @param datetime Date/time structure.
        !           589:    @return Number of formatted characters.
        !           590: 
        !           591:    The formatting string accepts the same specifiers as the standard C
        !           592:    function strftime.
        !           593: */
        !           594: TRIO_STRING_PUBLIC size_t
        !           595: trio_format_date_max
        !           596: TRIO_ARGS4((target, max, format, datetime),
        !           597:           char *target,
        !           598:           size_t max,
        !           599:           TRIO_CONST char *format,
        !           600:           TRIO_CONST struct tm *datetime)
        !           601: {
        !           602:   assert(target);
        !           603:   assert(format);
        !           604:   assert(datetime);
        !           605:   assert(max > 0);
        !           606:   
        !           607:   return strftime(target, max, format, datetime);
        !           608: }
        !           609: #endif /* !defined(TRIO_MINIMAL) */
        !           610: 
        !           611: 
        !           612: #if !defined(TRIO_MINIMAL)
        !           613: /**
        !           614:    Calculate a hash value for a string.
        !           615: 
        !           616:    @param string String to be calculated on.
        !           617:    @param type Hash function.
        !           618:    @return Calculated hash value.
        !           619: 
        !           620:    @p type can be one of the following
        !           621:    @li @c TRIO_HASH_PLAIN Plain hash function.
        !           622: */
        !           623: TRIO_STRING_PUBLIC unsigned long
        !           624: trio_hash
        !           625: TRIO_ARGS2((string, type),
        !           626:           TRIO_CONST char *string,
        !           627:           int type)
        !           628: {
        !           629:   unsigned long value = 0L;
        !           630:   char ch;
        !           631: 
        !           632:   assert(string);
        !           633:   
        !           634:   switch (type)
        !           635:     {
        !           636:     case TRIO_HASH_PLAIN:
        !           637:       while ( (ch = *string++) != NIL )
        !           638:        {
        !           639:          value *= 31;
        !           640:          value += (unsigned long)ch;
        !           641:        }
        !           642:       break;
        !           643:     default:
        !           644:       assert(FALSE);
        !           645:       break;
        !           646:     }
        !           647:   return value;
        !           648: }
        !           649: #endif /* !defined(TRIO_MINIMAL) */
        !           650: 
        !           651: 
        !           652: #if !defined(TRIO_MINIMAL)
        !           653: /**
        !           654:    Find first occurrence of a character in a string.
        !           655: 
        !           656:    @param string String to be searched.
        !           657:    @param character Character to be found.
        !           658:    @param A pointer to the found character, or NULL if character was not found.
        !           659:  */
        !           660: TRIO_STRING_PUBLIC char *
        !           661: trio_index
        !           662: TRIO_ARGS2((string, character),
        !           663:           TRIO_CONST char *string,
        !           664:           int character)
        !           665: {
        !           666:   assert(string);
        !           667: 
        !           668:   return strchr(string, character);
        !           669: }
        !           670: #endif /* !defined(TRIO_MINIMAL) */
        !           671: 
        !           672: 
        !           673: #if !defined(TRIO_MINIMAL)
        !           674: /**
        !           675:    Find last occurrence of a character in a string.
        !           676: 
        !           677:    @param string String to be searched.
        !           678:    @param character Character to be found.
        !           679:    @param A pointer to the found character, or NULL if character was not found.
        !           680:  */
        !           681: TRIO_STRING_PUBLIC char *
        !           682: trio_index_last
        !           683: TRIO_ARGS2((string, character),
        !           684:           TRIO_CONST char *string,
        !           685:           int character)
        !           686: {
        !           687:   assert(string);
        !           688: 
        !           689:   return strchr(string, character);
        !           690: }
        !           691: #endif /* !defined(TRIO_MINIMAL) */
        !           692: 
        !           693: 
        !           694: #if !defined(TRIO_MINIMAL)
        !           695: /**
        !           696:    Convert the alphabetic letters in the string to lower-case.
        !           697: 
        !           698:    @param target String to be converted.
        !           699:    @return Number of processed characters (converted or not).
        !           700: */
        !           701: TRIO_STRING_PUBLIC int
        !           702: trio_lower
        !           703: TRIO_ARGS1((target),
        !           704:           char *target)
        !           705: {
        !           706:   assert(target);
        !           707: 
        !           708:   return trio_span_function(target, target, trio_to_lower);
        !           709: }
        !           710: #endif /* !defined(TRIO_MINIMAL) */
        !           711: 
        !           712: 
        !           713: #if !defined(TRIO_MINIMAL)
        !           714: /**
        !           715:    Compare two strings using wildcards.
        !           716: 
        !           717:    @param string String to be searched.
        !           718:    @param pattern Pattern, including wildcards, to search for.
        !           719:    @return Boolean value indicating success or failure.
        !           720: 
        !           721:    Case-insensitive comparison.
        !           722:    
        !           723:    The following wildcards can be used
        !           724:    @li @c * Match any number of characters.
        !           725:    @li @c ? Match a single character.
        !           726: */
        !           727: TRIO_STRING_PUBLIC int
        !           728: trio_match
        !           729: TRIO_ARGS2((string, pattern),
        !           730:           TRIO_CONST char *string,
        !           731:           TRIO_CONST char *pattern)
        !           732: {
        !           733:   assert(string);
        !           734:   assert(pattern);
        !           735:   
        !           736:   for (; ('*' != *pattern); ++pattern, ++string)
        !           737:     {
        !           738:       if (NIL == *string)
        !           739:        {
        !           740:          return (NIL == *pattern);
        !           741:        }
        !           742:       if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern))
        !           743:          && ('?' != *pattern))
        !           744:        {
        !           745:          return FALSE;
        !           746:        }
        !           747:     }
        !           748:   /* two-line patch to prevent *too* much recursiveness: */
        !           749:   while ('*' == pattern[1])
        !           750:     pattern++;
        !           751: 
        !           752:   do
        !           753:     {
        !           754:       if ( trio_match(string, &pattern[1]) )
        !           755:        {
        !           756:          return TRUE;
        !           757:        }
        !           758:     }
        !           759:   while (*string++);
        !           760:   
        !           761:   return FALSE;
        !           762: }
        !           763: #endif /* !defined(TRIO_MINIMAL) */
        !           764: 
        !           765: 
        !           766: #if !defined(TRIO_MINIMAL)
        !           767: /**
        !           768:    Compare two strings using wildcards.
        !           769: 
        !           770:    @param string String to be searched.
        !           771:    @param pattern Pattern, including wildcards, to search for.
        !           772:    @return Boolean value indicating success or failure.
        !           773: 
        !           774:    Case-sensitive comparison.
        !           775:    
        !           776:    The following wildcards can be used
        !           777:    @li @c * Match any number of characters.
        !           778:    @li @c ? Match a single character.
        !           779: */
        !           780: TRIO_STRING_PUBLIC int
        !           781: trio_match_case
        !           782: TRIO_ARGS2((string, pattern),
        !           783:           TRIO_CONST char *string,
        !           784:           TRIO_CONST char *pattern)
        !           785: {
        !           786:   assert(string);
        !           787:   assert(pattern);
        !           788:   
        !           789:   for (; ('*' != *pattern); ++pattern, ++string)
        !           790:     {
        !           791:       if (NIL == *string)
        !           792:        {
        !           793:          return (NIL == *pattern);
        !           794:        }
        !           795:       if ((*string != *pattern)
        !           796:          && ('?' != *pattern))
        !           797:        {
        !           798:          return FALSE;
        !           799:        }
        !           800:     }
        !           801:   /* two-line patch to prevent *too* much recursiveness: */
        !           802:   while ('*' == pattern[1])
        !           803:     pattern++;
        !           804: 
        !           805:   do
        !           806:     {
        !           807:       if ( trio_match_case(string, &pattern[1]) )
        !           808:        {
        !           809:          return TRUE;
        !           810:        }
        !           811:     }
        !           812:   while (*string++);
        !           813:   
        !           814:   return FALSE;
        !           815: }
        !           816: #endif /* !defined(TRIO_MINIMAL) */
        !           817: 
        !           818: 
        !           819: #if !defined(TRIO_MINIMAL)
        !           820: /**
        !           821:    Execute a function on each character in string.
        !           822: 
        !           823:    @param target Target string.
        !           824:    @param source Source string.
        !           825:    @param Function Function to be executed.
        !           826:    @return Number of processed characters.
        !           827: */
        !           828: TRIO_STRING_PUBLIC size_t
        !           829: trio_span_function
        !           830: TRIO_ARGS3((target, source, Function),
        !           831:           char *target,
        !           832:           TRIO_CONST char *source,
        !           833:           int (*Function) TRIO_PROTO((int)))
        !           834: {
        !           835:   size_t count = 0;
        !           836: 
        !           837:   assert(target);
        !           838:   assert(source);
        !           839:   assert(Function);
        !           840:   
        !           841:   while (*source != NIL)
        !           842:     {
        !           843:       *target++ = Function(*source++);
        !           844:       count++;
        !           845:     }
        !           846:   return count;
        !           847: }
        !           848: #endif /* !defined(TRIO_MINIMAL) */
        !           849: 
        !           850: 
        !           851: #if !defined(TRIO_MINIMAL)
        !           852: /**
        !           853:    Search for a substring in a string.
        !           854: 
        !           855:    @param string String to be searched.
        !           856:    @param substring String to be found.
        !           857:    @return Pointer to first occurrence of @p substring in @p string, or NULL
        !           858:    if no match was found.
        !           859: */
        !           860: TRIO_STRING_PUBLIC char *
        !           861: trio_substring
        !           862: TRIO_ARGS2((string, substring),
        !           863:           TRIO_CONST char *string,
        !           864:           TRIO_CONST char *substring)
        !           865: {
        !           866:   assert(string);
        !           867:   assert(substring);
        !           868: 
        !           869:   return strstr(string, substring);
        !           870: }
        !           871: #endif /* !defined(TRIO_MINIMAL) */
        !           872: 
        !           873: 
        !           874: #if !defined(TRIO_MINIMAL)
        !           875: /**
        !           876:    Search for a substring in the first @p max characters of a string.
        !           877: 
        !           878:    @param string String to be searched.
        !           879:    @param max Maximum characters to be searched.
        !           880:    @param substring String to be found.
        !           881:    @return Pointer to first occurrence of @p substring in @p string, or NULL
        !           882:    if no match was found.
        !           883: */
        !           884: TRIO_STRING_PUBLIC char *
        !           885: trio_substring_max
        !           886: TRIO_ARGS3((string, max, substring),
        !           887:           TRIO_CONST char *string,
        !           888:           size_t max,
        !           889:           TRIO_CONST char *substring)
        !           890: {
        !           891:   size_t count;
        !           892:   size_t size;
        !           893:   char *result = NULL;
        !           894: 
        !           895:   assert(string);
        !           896:   assert(substring);
        !           897:   
        !           898:   size = trio_length(substring);
        !           899:   if (size <= max)
        !           900:     {
        !           901:       for (count = 0; count <= max - size; count++)
        !           902:        {
        !           903:          if (trio_equal_max(substring, size, &string[count]))
        !           904:            {
        !           905:              result = (char *)&string[count];
        !           906:              break;
        !           907:            }
        !           908:        }
        !           909:     }
        !           910:   return result;
        !           911: }
        !           912: #endif /* !defined(TRIO_MINIMAL) */
        !           913: 
        !           914: 
        !           915: #if !defined(TRIO_MINIMAL)
        !           916: /**
        !           917:    Tokenize string.
        !           918: 
        !           919:    @param string String to be tokenized.
        !           920:    @param tokens String containing list of delimiting characters.
        !           921:    @return Start of new token.
        !           922: 
        !           923:    @warning @p string will be destroyed.
        !           924: */
        !           925: TRIO_STRING_PUBLIC char *
        !           926: trio_tokenize
        !           927: TRIO_ARGS2((string, delimiters),
        !           928:           char *string,
        !           929:           TRIO_CONST char *delimiters)
        !           930: {
        !           931:   assert(delimiters);
        !           932:   
        !           933:   return strtok(string, delimiters);
        !           934: }
        !           935: #endif /* !defined(TRIO_MINIMAL) */
        !           936: 
        !           937: 
        !           938: /**
        !           939:    Convert string to floating-point number.
        !           940: 
        !           941:    @param source String to be converted.
        !           942:    @param endp Pointer to end of the converted string.
        !           943:    @return A floating-point number.
        !           944: 
        !           945:    The following Extended Backus-Naur form is used
        !           946:    @verbatim
        !           947:    double        ::= [ <sign> ]
        !           948:                      ( <number> |
        !           949:                        <number> <decimal_point> <number> |
        !           950:                        <decimal_point> <number> )
        !           951:                      [ <exponential> [ <sign> ] <number> ]
        !           952:    number        ::= 1*( <digit> )
        !           953:    digit         ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
        !           954:    exponential   ::= ( 'e' | 'E' )
        !           955:    sign          ::= ( '-' | '+' )
        !           956:    decimal_point ::= '.'
        !           957:    @endverbatim
        !           958: */
        !           959: /* FIXME: Add EBNF for hex-floats */
        !           960: TRIO_STRING_PUBLIC trio_long_double_t
        !           961: trio_to_long_double
        !           962: TRIO_ARGS2((source, endp),
        !           963:           TRIO_CONST char *source,
        !           964:           char **endp)
        !           965: {
        !           966: #if defined(USE_STRTOLD)
        !           967:   return strtold(source, endp);
        !           968: #else
        !           969:   int isNegative = FALSE;
        !           970:   int isExponentNegative = FALSE;
        !           971:   trio_long_double_t integer = 0.0;
        !           972:   trio_long_double_t fraction = 0.0;
        !           973:   unsigned long exponent = 0;
        !           974:   trio_long_double_t base;
        !           975:   trio_long_double_t fracdiv = 1.0;
        !           976:   trio_long_double_t value = 0.0;
        !           977: 
        !           978:   /* First try hex-floats */
        !           979:   if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X')))
        !           980:     {
        !           981:       base = 16.0;
        !           982:       source += 2;
        !           983:       while (isxdigit((int)*source))
        !           984:        {
        !           985:          integer *= base;
        !           986:          integer += (isdigit((int)*source)
        !           987:                      ? (*source - '0')
        !           988:                      : 10 + (trio_to_upper((int)*source) - 'A'));
        !           989:          source++;
        !           990:        }
        !           991:       if (*source == '.')
        !           992:        {
        !           993:          source++;
        !           994:          while (isxdigit((int)*source))
        !           995:            {
        !           996:              fracdiv /= base;
        !           997:              fraction += fracdiv * (isdigit((int)*source)
        !           998:                                     ? (*source - '0')
        !           999:                                     : 10 + (trio_to_upper((int)*source) - 'A'));
        !          1000:              source++;
        !          1001:            }
        !          1002:          if ((*source == 'p') || (*source == 'P'))
        !          1003:            {
        !          1004:              source++;
        !          1005:              if ((*source == '+') || (*source == '-'))
        !          1006:                {
        !          1007:                  isExponentNegative = (*source == '-');
        !          1008:                  source++;
        !          1009:                }
        !          1010:              while (isdigit((int)*source))
        !          1011:                {
        !          1012:                  exponent *= 10;
        !          1013:                  exponent += (*source - '0');
        !          1014:                  source++;
        !          1015:                }
        !          1016:            }
        !          1017:        }
        !          1018:       /* For later use with exponent */
        !          1019:       base = 2.0;
        !          1020:     }
        !          1021:   else /* Then try normal decimal floats */
        !          1022:     {
        !          1023:       base = 10.0;
        !          1024:       isNegative = (*source == '-');
        !          1025:       /* Skip sign */
        !          1026:       if ((*source == '+') || (*source == '-'))
        !          1027:        source++;
        !          1028: 
        !          1029:       /* Integer part */
        !          1030:       while (isdigit((int)*source))
        !          1031:        {
        !          1032:          integer *= base;
        !          1033:          integer += (*source - '0');
        !          1034:          source++;
        !          1035:        }
        !          1036: 
        !          1037:       if (*source == '.')
        !          1038:        {
        !          1039:          source++; /* skip decimal point */
        !          1040:          while (isdigit((int)*source))
        !          1041:            {
        !          1042:              fracdiv /= base;
        !          1043:              fraction += (*source - '0') * fracdiv;
        !          1044:              source++;
        !          1045:            }
        !          1046:        }
        !          1047:       if ((*source == 'e')
        !          1048:          || (*source == 'E')
        !          1049: #if TRIO_MICROSOFT
        !          1050:          || (*source == 'd')
        !          1051:          || (*source == 'D')
        !          1052: #endif
        !          1053:          )
        !          1054:        {
        !          1055:          source++; /* Skip exponential indicator */
        !          1056:          isExponentNegative = (*source == '-');
        !          1057:          if ((*source == '+') || (*source == '-'))
        !          1058:            source++;
        !          1059:          while (isdigit((int)*source))
        !          1060:            {
        !          1061:              exponent *= (int)base;
        !          1062:              exponent += (*source - '0');
        !          1063:              source++;
        !          1064:            }
        !          1065:        }
        !          1066:     }
        !          1067:   
        !          1068:   value = integer + fraction;
        !          1069:   if (exponent != 0)
        !          1070:     {
        !          1071:       if (isExponentNegative)
        !          1072:        value /= pow(base, (double)exponent);
        !          1073:       else
        !          1074:        value *= pow(base, (double)exponent);
        !          1075:     }
        !          1076:   if (isNegative)
        !          1077:     value = -value;
        !          1078: 
        !          1079:   if (endp)
        !          1080:     *endp = (char *)source;
        !          1081:   return value;
        !          1082: #endif
        !          1083: }
        !          1084: 
        !          1085: 
        !          1086: /**
        !          1087:    Convert string to floating-point number.
        !          1088: 
        !          1089:    @param source String to be converted.
        !          1090:    @param endp Pointer to end of the converted string.
        !          1091:    @return A floating-point number.
        !          1092: 
        !          1093:    See @ref trio_to_long_double.
        !          1094: */
        !          1095: TRIO_STRING_PUBLIC double
        !          1096: trio_to_double
        !          1097: TRIO_ARGS2((source, endp),
        !          1098:           TRIO_CONST char *source,
        !          1099:           char **endp)
        !          1100: {
        !          1101: #if defined(USE_STRTOD)
        !          1102:   return strtod(source, endp);
        !          1103: #else
        !          1104:   return (double)trio_to_long_double(source, endp);
        !          1105: #endif
        !          1106: }
        !          1107: 
        !          1108: #if !defined(TRIO_MINIMAL)
        !          1109: /**
        !          1110:    Convert string to floating-point number.
        !          1111: 
        !          1112:    @param source String to be converted.
        !          1113:    @param endp Pointer to end of the converted string.
        !          1114:    @return A floating-point number.
        !          1115: 
        !          1116:    See @ref trio_to_long_double.
        !          1117: */
        !          1118: TRIO_STRING_PUBLIC float
        !          1119: trio_to_float
        !          1120: TRIO_ARGS2((source, endp),
        !          1121:           TRIO_CONST char *source,
        !          1122:           char **endp)
        !          1123: {
        !          1124: #if defined(USE_STRTOF)
        !          1125:   return strtof(source, endp);
        !          1126: #else
        !          1127:   return (float)trio_to_long_double(source, endp);
        !          1128: #endif
        !          1129: }
        !          1130: #endif /* !defined(TRIO_MINIMAL) */
        !          1131: 
        !          1132: 
        !          1133: /**
        !          1134:    Convert string to signed integer.
        !          1135: 
        !          1136:    @param string String to be converted.
        !          1137:    @param endp Pointer to end of converted string.
        !          1138:    @param base Radix number of number.
        !          1139: */
        !          1140: TRIO_STRING_PUBLIC long
        !          1141: trio_to_long
        !          1142: TRIO_ARGS3((string, endp, base),
        !          1143:           TRIO_CONST char *string,
        !          1144:           char **endp,
        !          1145:           int base)
        !          1146: {
        !          1147:   assert(string);
        !          1148:   assert((base >= 2) && (base <= 36));
        !          1149:   
        !          1150:   return strtol(string, endp, base);
        !          1151: }
        !          1152: 
        !          1153: 
        !          1154: #if !defined(TRIO_MINIMAL)
        !          1155: /**
        !          1156:    Convert one alphabetic letter to lower-case.
        !          1157: 
        !          1158:    @param source The letter to be converted.
        !          1159:    @return The converted letter.
        !          1160: */
        !          1161: TRIO_STRING_PUBLIC int
        !          1162: trio_to_lower
        !          1163: TRIO_ARGS1((source),
        !          1164:           int source)
        !          1165: {
        !          1166: #if defined(USE_TOLOWER)
        !          1167:   
        !          1168:   return tolower(source);
        !          1169:   
        !          1170: #else
        !          1171: 
        !          1172:   /* Does not handle locales or non-contiguous alphabetic characters */
        !          1173:   return ((source >= (int)'A') && (source <= (int)'Z'))
        !          1174:     ? source - 'A' + 'a'
        !          1175:     : source;
        !          1176:   
        !          1177: #endif
        !          1178: }
        !          1179: #endif /* !defined(TRIO_MINIMAL) */
        !          1180: 
        !          1181: #if !defined(TRIO_MINIMAL)
        !          1182: /**
        !          1183:    Convert string to unsigned integer.
        !          1184: 
        !          1185:    @param string String to be converted.
        !          1186:    @param endp Pointer to end of converted string.
        !          1187:    @param base Radix number of number.
        !          1188: */
        !          1189: TRIO_STRING_PUBLIC unsigned long
        !          1190: trio_to_unsigned_long
        !          1191: TRIO_ARGS3((string, endp, base),
        !          1192:           TRIO_CONST char *string,
        !          1193:           char **endp,
        !          1194:           int base)
        !          1195: {
        !          1196:   assert(string);
        !          1197:   assert((base >= 2) && (base <= 36));
        !          1198:   
        !          1199:   return strtoul(string, endp, base);
        !          1200: }
        !          1201: #endif /* !defined(TRIO_MINIMAL) */
        !          1202: 
        !          1203: 
        !          1204: /**
        !          1205:    Convert one alphabetic letter to upper-case.
        !          1206: 
        !          1207:    @param source The letter to be converted.
        !          1208:    @return The converted letter.
        !          1209: */
        !          1210: TRIO_STRING_PUBLIC int
        !          1211: trio_to_upper
        !          1212: TRIO_ARGS1((source),
        !          1213:           int source)
        !          1214: {
        !          1215: #if defined(USE_TOUPPER)
        !          1216:   
        !          1217:   return toupper(source);
        !          1218:   
        !          1219: #else
        !          1220: 
        !          1221:   /* Does not handle locales or non-contiguous alphabetic characters */
        !          1222:   return ((source >= (int)'a') && (source <= (int)'z'))
        !          1223:     ? source - 'a' + 'A'
        !          1224:     : source;
        !          1225:   
        !          1226: #endif
        !          1227: }
        !          1228: 
        !          1229: #if !defined(TRIO_MINIMAL)
        !          1230: /**
        !          1231:    Convert the alphabetic letters in the string to upper-case.
        !          1232: 
        !          1233:    @param target The string to be converted.
        !          1234:    @return The number of processed characters (converted or not).
        !          1235: */
        !          1236: TRIO_STRING_PUBLIC int
        !          1237: trio_upper
        !          1238: TRIO_ARGS1((target),
        !          1239:           char *target)
        !          1240: {
        !          1241:   assert(target);
        !          1242: 
        !          1243:   return trio_span_function(target, target, trio_to_upper);
        !          1244: }
        !          1245: #endif /* !defined(TRIO_MINIMAL) */
        !          1246: 
        !          1247: 
        !          1248: /** @} End of StaticStrings */
        !          1249: 
        !          1250: 
        !          1251: /*************************************************************************
        !          1252:  * Dynamic String Functions
        !          1253:  */
        !          1254: 
        !          1255: #if defined(TRIO_DOCUMENTATION)
        !          1256: # include "doc/doc_dynamic.h"
        !          1257: #endif
        !          1258: /** @addtogroup DynamicStrings
        !          1259:     @{
        !          1260: */
        !          1261: 
        !          1262: /*
        !          1263:  * TrioStringAlloc
        !          1264:  */
        !          1265: TRIO_STRING_PRIVATE trio_string_t *
        !          1266: TrioStringAlloc(TRIO_NOARGS)
        !          1267: {
        !          1268:   trio_string_t *self;
        !          1269:   
        !          1270:   self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t));
        !          1271:   if (self)
        !          1272:     {
        !          1273:       self->content = NULL;
        !          1274:       self->length = 0;
        !          1275:       self->allocated = 0;
        !          1276:     }
        !          1277:   return self;
        !          1278: }
        !          1279: 
        !          1280: 
        !          1281: /*
        !          1282:  * TrioStringGrow
        !          1283:  *
        !          1284:  * The size of the string will be increased by 'delta' characters. If
        !          1285:  * 'delta' is zero, the size will be doubled.
        !          1286:  */
        !          1287: TRIO_STRING_PRIVATE BOOLEAN_T
        !          1288: TrioStringGrow
        !          1289: TRIO_ARGS2((self, delta),
        !          1290:           trio_string_t *self,
        !          1291:           size_t delta)
        !          1292: {
        !          1293:   BOOLEAN_T status = FALSE;
        !          1294:   char *new_content;
        !          1295:   size_t new_size;
        !          1296: 
        !          1297:   new_size = (delta == 0)
        !          1298:     ? ( (self->allocated == 0) ? 1 : self->allocated * 2 )
        !          1299:     : self->allocated + delta;
        !          1300:   
        !          1301:   new_content = (char *)TRIO_REALLOC(self->content, new_size);
        !          1302:   if (new_content)
        !          1303:     {
        !          1304:       self->content = new_content;
        !          1305:       self->allocated = new_size;
        !          1306:       status = TRUE;
        !          1307:     }
        !          1308:   return status;
        !          1309: }
        !          1310: 
        !          1311: 
        !          1312: #if !defined(TRIO_MINIMAL)
        !          1313: /*
        !          1314:  * TrioStringGrowTo
        !          1315:  *
        !          1316:  * The size of the string will be increased to 'length' plus one characters.
        !          1317:  * If 'length' is less than the original size, the original size will be
        !          1318:  * used (that is, the size of the string is never decreased).
        !          1319:  */
        !          1320: TRIO_STRING_PRIVATE BOOLEAN_T
        !          1321: TrioStringGrowTo
        !          1322: TRIO_ARGS2((self, length),
        !          1323:           trio_string_t *self,
        !          1324:           size_t length)
        !          1325: {
        !          1326:   length++; /* Room for terminating zero */
        !          1327:   return (self->allocated < length)
        !          1328:     ? TrioStringGrow(self, length - self->allocated)
        !          1329:     : TRUE;
        !          1330: }
        !          1331: #endif /* !defined(TRIO_MINIMAL) */
        !          1332: 
        !          1333: 
        !          1334: #if !defined(TRIO_MINIMAL)
        !          1335: /**
        !          1336:    Create a new dynamic string.
        !          1337:    
        !          1338:    @param initial_size Initial size of the buffer.
        !          1339:    @return Newly allocated dynamic string, or NULL if memory allocation failed.
        !          1340: */
        !          1341: TRIO_STRING_PUBLIC trio_string_t *
        !          1342: trio_string_create
        !          1343: TRIO_ARGS1((initial_size),
        !          1344:           int initial_size)
        !          1345: {
        !          1346:   trio_string_t *self;
        !          1347: 
        !          1348:   self = TrioStringAlloc();
        !          1349:   if (self)
        !          1350:     {
        !          1351:       if (TrioStringGrow(self,
        !          1352:                         (size_t)((initial_size > 0) ? initial_size : 1)))
        !          1353:        {
        !          1354:          self->content[0] = (char)0;
        !          1355:          self->allocated = initial_size;
        !          1356:        }
        !          1357:       else
        !          1358:        {
        !          1359:          trio_string_destroy(self);
        !          1360:          self = NULL;
        !          1361:        }
        !          1362:     }
        !          1363:   return self;
        !          1364: }
        !          1365: #endif /* !defined(TRIO_MINIMAL) */
        !          1366: 
        !          1367: 
        !          1368: /**
        !          1369:    Deallocate the dynamic string and its contents.
        !          1370:    
        !          1371:    @param self Dynamic string
        !          1372: */
        !          1373: TRIO_STRING_PUBLIC void
        !          1374: trio_string_destroy
        !          1375: TRIO_ARGS1((self),
        !          1376:           trio_string_t *self)
        !          1377: {
        !          1378:   assert(self);
        !          1379:   
        !          1380:   if (self)
        !          1381:     {
        !          1382:       trio_destroy(self->content);
        !          1383:       TRIO_FREE(self);
        !          1384:     }
        !          1385: }
        !          1386: 
        !          1387: 
        !          1388: #if !defined(TRIO_MINIMAL)
        !          1389: /**
        !          1390:    Get a pointer to the content.
        !          1391:    
        !          1392:    @param self Dynamic string.
        !          1393:    @param offset Offset into content.
        !          1394:    @return Pointer to the content.
        !          1395:    
        !          1396:    @p Offset can be zero, positive, or negative. If @p offset is zero,
        !          1397:    then the start of the content will be returned. If @p offset is positive,
        !          1398:    then a pointer to @p offset number of characters from the beginning of the
        !          1399:    content is returned. If @p offset is negative, then a pointer to @p offset
        !          1400:    number of characters from the ending of the string, starting at the
        !          1401:    terminating zero, is returned.
        !          1402: */
        !          1403: TRIO_STRING_PUBLIC char *
        !          1404: trio_string_get
        !          1405: TRIO_ARGS2((self, offset),
        !          1406:           trio_string_t *self,
        !          1407:           int offset)
        !          1408: {
        !          1409:   char *result = NULL;
        !          1410:   
        !          1411:   assert(self);
        !          1412: 
        !          1413:   if (self->content != NULL)
        !          1414:     {
        !          1415:       if (self->length == 0)
        !          1416:        {
        !          1417:          (void)trio_string_length(self);
        !          1418:        }
        !          1419:       if (offset >= 0)
        !          1420:        {
        !          1421:          if (offset > (int)self->length)
        !          1422:            {
        !          1423:              offset = self->length;
        !          1424:            }
        !          1425:        }
        !          1426:       else
        !          1427:        {
        !          1428:          offset += self->length + 1;
        !          1429:          if (offset < 0)
        !          1430:            {
        !          1431:              offset = 0;
        !          1432:            }
        !          1433:        }
        !          1434:       result = &(self->content[offset]);
        !          1435:     }
        !          1436:   return result;
        !          1437: }
        !          1438: #endif /* !defined(TRIO_MINIMAL) */
        !          1439: 
        !          1440: 
        !          1441: /**
        !          1442:    Extract the content.
        !          1443:    
        !          1444:    @param self Dynamic String
        !          1445:    @return Content of dynamic string.
        !          1446:    
        !          1447:    The content is removed from the dynamic string. This enables destruction
        !          1448:    of the dynamic string without deallocation of the content.
        !          1449: */
        !          1450: TRIO_STRING_PUBLIC char *
        !          1451: trio_string_extract
        !          1452: TRIO_ARGS1((self),
        !          1453:           trio_string_t *self)
        !          1454: {
        !          1455:   char *result;
        !          1456:   
        !          1457:   assert(self);
        !          1458: 
        !          1459:   result = self->content;
        !          1460:   /* FIXME: Allocate new empty buffer? */
        !          1461:   self->content = NULL;
        !          1462:   self->length = self->allocated = 0;
        !          1463:   return result;
        !          1464: }
        !          1465: 
        !          1466: 
        !          1467: #if !defined(TRIO_MINIMAL)
        !          1468: /**
        !          1469:    Set the content of the dynamic string.
        !          1470:    
        !          1471:    @param self Dynamic String
        !          1472:    @param buffer The new content.
        !          1473:    
        !          1474:    Sets the content of the dynamic string to a copy @p buffer.
        !          1475:    An existing content will be deallocated first, if necessary.
        !          1476:    
        !          1477:    @remark
        !          1478:    This function will make a copy of @p buffer.
        !          1479:    You are responsible for deallocating @p buffer yourself.
        !          1480: */
        !          1481: TRIO_STRING_PUBLIC void
        !          1482: trio_xstring_set
        !          1483: TRIO_ARGS2((self, buffer),
        !          1484:           trio_string_t *self,
        !          1485:           char *buffer)
        !          1486: {
        !          1487:   assert(self);
        !          1488: 
        !          1489:   trio_destroy(self->content);
        !          1490:   self->content = trio_duplicate(buffer);
        !          1491: }
        !          1492: #endif /* !defined(TRIO_MINIMAL) */
        !          1493: 
        !          1494: 
        !          1495: /*
        !          1496:  * trio_string_size
        !          1497:  */
        !          1498: TRIO_STRING_PUBLIC int
        !          1499: trio_string_size
        !          1500: TRIO_ARGS1((self),
        !          1501:           trio_string_t *self)
        !          1502: {
        !          1503:   assert(self);
        !          1504: 
        !          1505:   return self->allocated;
        !          1506: }
        !          1507: 
        !          1508: 
        !          1509: /*
        !          1510:  * trio_string_terminate
        !          1511:  */
        !          1512: TRIO_STRING_PUBLIC void
        !          1513: trio_string_terminate
        !          1514: TRIO_ARGS1((self),
        !          1515:           trio_string_t *self)
        !          1516: {
        !          1517:   trio_xstring_append_char(self, 0);
        !          1518: }
        !          1519: 
        !          1520: 
        !          1521: #if !defined(TRIO_MINIMAL)
        !          1522: /**
        !          1523:    Append the second string to the first.
        !          1524:    
        !          1525:    @param self Dynamic string to be modified.
        !          1526:    @param other Dynamic string to copy from.
        !          1527:    @return Boolean value indicating success or failure.
        !          1528: */
        !          1529: TRIO_STRING_PUBLIC int
        !          1530: trio_string_append
        !          1531: TRIO_ARGS2((self, other),
        !          1532:           trio_string_t *self,
        !          1533:           trio_string_t *other)
        !          1534: {
        !          1535:   size_t length;
        !          1536:   
        !          1537:   assert(self);
        !          1538:   assert(other);
        !          1539: 
        !          1540:   length = self->length + other->length;
        !          1541:   if (!TrioStringGrowTo(self, length))
        !          1542:     goto error;
        !          1543:   trio_copy(&self->content[self->length], other->content);
        !          1544:   self->length = length;
        !          1545:   return TRUE;
        !          1546:   
        !          1547:  error:
        !          1548:   return FALSE;
        !          1549: }
        !          1550: #endif /* !defined(TRIO_MINIMAL) */
        !          1551: 
        !          1552: 
        !          1553: #if !defined(TRIO_MINIMAL)
        !          1554: /*
        !          1555:  * trio_xstring_append
        !          1556:  */
        !          1557: TRIO_STRING_PUBLIC int
        !          1558: trio_xstring_append
        !          1559: TRIO_ARGS2((self, other),
        !          1560:           trio_string_t *self,
        !          1561:           TRIO_CONST char *other)
        !          1562: {
        !          1563:   size_t length;
        !          1564:   
        !          1565:   assert(self);
        !          1566:   assert(other);
        !          1567: 
        !          1568:   length = self->length + trio_length(other);
        !          1569:   if (!TrioStringGrowTo(self, length))
        !          1570:     goto error;
        !          1571:   trio_copy(&self->content[self->length], other);
        !          1572:   self->length = length;
        !          1573:   return TRUE;
        !          1574:   
        !          1575:  error:
        !          1576:   return FALSE;
        !          1577: }
        !          1578: #endif /* !defined(TRIO_MINIMAL) */
        !          1579: 
        !          1580: 
        !          1581: /*
        !          1582:  * trio_xstring_append_char
        !          1583:  */
        !          1584: TRIO_STRING_PUBLIC int
        !          1585: trio_xstring_append_char
        !          1586: TRIO_ARGS2((self, character),
        !          1587:           trio_string_t *self,
        !          1588:           char character)
        !          1589: {
        !          1590:   assert(self);
        !          1591: 
        !          1592:   if ((int)self->length >= trio_string_size(self))
        !          1593:     {
        !          1594:       if (!TrioStringGrow(self, 0))
        !          1595:        goto error;
        !          1596:     }
        !          1597:   self->content[self->length] = character;
        !          1598:   self->length++;
        !          1599:   return TRUE;
        !          1600:   
        !          1601:  error:
        !          1602:   return FALSE;
        !          1603: }
        !          1604: 
        !          1605: 
        !          1606: #if !defined(TRIO_MINIMAL)
        !          1607: /**
        !          1608:    Search for the first occurrence of second parameter in the first.
        !          1609:    
        !          1610:    @param self Dynamic string to be modified.
        !          1611:    @param other Dynamic string to copy from.
        !          1612:    @return Boolean value indicating success or failure.
        !          1613: */
        !          1614: TRIO_STRING_PUBLIC int
        !          1615: trio_string_contains
        !          1616: TRIO_ARGS2((self, other),
        !          1617:           trio_string_t *self,
        !          1618:           trio_string_t *other)
        !          1619: {
        !          1620:   assert(self);
        !          1621:   assert(other);
        !          1622: 
        !          1623:   return trio_contains(self->content, other->content);
        !          1624: }
        !          1625: #endif /* !defined(TRIO_MINIMAL) */
        !          1626: 
        !          1627: 
        !          1628: #if !defined(TRIO_MINIMAL)
        !          1629: /*
        !          1630:  * trio_xstring_contains
        !          1631:  */
        !          1632: TRIO_STRING_PUBLIC int
        !          1633: trio_xstring_contains
        !          1634: TRIO_ARGS2((self, other),
        !          1635:           trio_string_t *self,
        !          1636:           TRIO_CONST char *other)
        !          1637: {
        !          1638:   assert(self);
        !          1639:   assert(other);
        !          1640: 
        !          1641:   return trio_contains(self->content, other);
        !          1642: }
        !          1643: #endif /* !defined(TRIO_MINIMAL) */
        !          1644: 
        !          1645: 
        !          1646: #if !defined(TRIO_MINIMAL)
        !          1647: /*
        !          1648:  * trio_string_copy
        !          1649:  */
        !          1650: TRIO_STRING_PUBLIC int
        !          1651: trio_string_copy
        !          1652: TRIO_ARGS2((self, other),
        !          1653:           trio_string_t *self,
        !          1654:           trio_string_t *other)
        !          1655: {
        !          1656:   assert(self);
        !          1657:   assert(other);
        !          1658: 
        !          1659:   self->length = 0;
        !          1660:   return trio_string_append(self, other);
        !          1661: }
        !          1662: #endif /* !defined(TRIO_MINIMAL) */
        !          1663: 
        !          1664: 
        !          1665: #if !defined(TRIO_MINIMAL)
        !          1666: /*
        !          1667:  * trio_xstring_copy
        !          1668:  */
        !          1669: TRIO_STRING_PUBLIC int
        !          1670: trio_xstring_copy
        !          1671: TRIO_ARGS2((self, other),
        !          1672:           trio_string_t *self,
        !          1673:           TRIO_CONST char *other)
        !          1674: {
        !          1675:   assert(self);
        !          1676:   assert(other);
        !          1677: 
        !          1678:   self->length = 0;
        !          1679:   return trio_xstring_append(self, other);
        !          1680: }
        !          1681: #endif /* !defined(TRIO_MINIMAL) */
        !          1682: 
        !          1683: 
        !          1684: #if !defined(TRIO_MINIMAL)
        !          1685: /*
        !          1686:  * trio_string_duplicate
        !          1687:  */
        !          1688: TRIO_STRING_PUBLIC trio_string_t *
        !          1689: trio_string_duplicate
        !          1690: TRIO_ARGS1((other),
        !          1691:           trio_string_t *other)
        !          1692: {
        !          1693:   trio_string_t *self;
        !          1694:   
        !          1695:   assert(other);
        !          1696: 
        !          1697:   self = TrioStringAlloc();
        !          1698:   if (self)
        !          1699:     {
        !          1700:       self->content = TrioDuplicateMax(other->content, other->length);
        !          1701:       if (self->content)
        !          1702:        {
        !          1703:          self->length = other->length;
        !          1704:          self->allocated = self->length + 1;
        !          1705:        }
        !          1706:       else
        !          1707:        {
        !          1708:          self->length = self->allocated = 0;
        !          1709:        }
        !          1710:     }
        !          1711:   return self;
        !          1712: }
        !          1713: #endif /* !defined(TRIO_MINIMAL) */
        !          1714: 
        !          1715: 
        !          1716: /*
        !          1717:  * trio_xstring_duplicate
        !          1718:  */
        !          1719: TRIO_STRING_PUBLIC trio_string_t *
        !          1720: trio_xstring_duplicate
        !          1721: TRIO_ARGS1((other),
        !          1722:           TRIO_CONST char *other)
        !          1723: {
        !          1724:   trio_string_t *self;
        !          1725:   
        !          1726:   assert(other);
        !          1727: 
        !          1728:   self = TrioStringAlloc();
        !          1729:   if (self)
        !          1730:     {
        !          1731:       self->content = TrioDuplicateMax(other, trio_length(other));
        !          1732:       if (self->content)
        !          1733:        {
        !          1734:          self->length = trio_length(self->content);
        !          1735:          self->allocated = self->length + 1;
        !          1736:        }
        !          1737:       else
        !          1738:        {
        !          1739:          self->length = self->allocated = 0;
        !          1740:        }
        !          1741:     }
        !          1742:   return self;
        !          1743: }
        !          1744: 
        !          1745: 
        !          1746: #if !defined(TRIO_MINIMAL)
        !          1747: /*
        !          1748:  * trio_string_equal
        !          1749:  */
        !          1750: TRIO_STRING_PUBLIC int
        !          1751: trio_string_equal
        !          1752: TRIO_ARGS2((self, other),
        !          1753:           trio_string_t *self,
        !          1754:           trio_string_t *other)
        !          1755: {
        !          1756:   assert(self);
        !          1757:   assert(other);
        !          1758: 
        !          1759:   return trio_equal(self->content, other->content);
        !          1760: }
        !          1761: #endif /* !defined(TRIO_MINIMAL) */
        !          1762: 
        !          1763: 
        !          1764: #if !defined(TRIO_MINIMAL)
        !          1765: /*
        !          1766:  * trio_xstring_equal
        !          1767:  */
        !          1768: TRIO_STRING_PUBLIC int
        !          1769: trio_xstring_equal
        !          1770: TRIO_ARGS2((self, other),
        !          1771:           trio_string_t *self,
        !          1772:           TRIO_CONST char *other)
        !          1773: {
        !          1774:   assert(self);
        !          1775:   assert(other);
        !          1776: 
        !          1777:   return trio_equal(self->content, other);
        !          1778: }
        !          1779: #endif /* !defined(TRIO_MINIMAL) */
        !          1780: 
        !          1781: 
        !          1782: #if !defined(TRIO_MINIMAL)
        !          1783: /*
        !          1784:  * trio_string_equal_max
        !          1785:  */
        !          1786: TRIO_STRING_PUBLIC int
        !          1787: trio_string_equal_max
        !          1788: TRIO_ARGS3((self, max, other),
        !          1789:           trio_string_t *self,
        !          1790:           size_t max,
        !          1791:           trio_string_t *other)
        !          1792: {
        !          1793:   assert(self);
        !          1794:   assert(other);
        !          1795: 
        !          1796:   return trio_equal_max(self->content, max, other->content);
        !          1797: }
        !          1798: #endif /* !defined(TRIO_MINIMAL) */
        !          1799: 
        !          1800: 
        !          1801: #if !defined(TRIO_MINIMAL)
        !          1802: /*
        !          1803:  * trio_xstring_equal_max
        !          1804:  */
        !          1805: TRIO_STRING_PUBLIC int
        !          1806: trio_xstring_equal_max
        !          1807: TRIO_ARGS3((self, max, other),
        !          1808:           trio_string_t *self,
        !          1809:           size_t max,
        !          1810:           TRIO_CONST char *other)
        !          1811: {
        !          1812:   assert(self);
        !          1813:   assert(other);
        !          1814: 
        !          1815:   return trio_equal_max(self->content, max, other);
        !          1816: }
        !          1817: #endif /* !defined(TRIO_MINIMAL) */
        !          1818: 
        !          1819: 
        !          1820: #if !defined(TRIO_MINIMAL)
        !          1821: /*
        !          1822:  * trio_string_equal_case
        !          1823:  */
        !          1824: TRIO_STRING_PUBLIC int
        !          1825: trio_string_equal_case
        !          1826: TRIO_ARGS2((self, other),
        !          1827:           trio_string_t *self,
        !          1828:           trio_string_t *other)
        !          1829: {
        !          1830:   assert(self);
        !          1831:   assert(other);
        !          1832: 
        !          1833:   return trio_equal_case(self->content, other->content);
        !          1834: }
        !          1835: #endif /* !defined(TRIO_MINIMAL) */
        !          1836: 
        !          1837: 
        !          1838: #if !defined(TRIO_MINIMAL)
        !          1839: /*
        !          1840:  * trio_xstring_equal_case
        !          1841:  */
        !          1842: TRIO_STRING_PUBLIC int
        !          1843: trio_xstring_equal_case
        !          1844: TRIO_ARGS2((self, other),
        !          1845:           trio_string_t *self,
        !          1846:           TRIO_CONST char *other)
        !          1847: {
        !          1848:   assert(self);
        !          1849:   assert(other);
        !          1850: 
        !          1851:   return trio_equal_case(self->content, other);
        !          1852: }
        !          1853: #endif /* !defined(TRIO_MINIMAL) */
        !          1854: 
        !          1855: 
        !          1856: #if !defined(TRIO_MINIMAL)
        !          1857: /*
        !          1858:  * trio_string_equal_case_max
        !          1859:  */
        !          1860: TRIO_STRING_PUBLIC int
        !          1861: trio_string_equal_case_max
        !          1862: TRIO_ARGS3((self, max, other),
        !          1863:           trio_string_t *self,
        !          1864:           size_t max,
        !          1865:           trio_string_t *other)
        !          1866: {
        !          1867:   assert(self);
        !          1868:   assert(other);
        !          1869: 
        !          1870:   return trio_equal_case_max(self->content, max, other->content);
        !          1871: }
        !          1872: #endif /* !defined(TRIO_MINIMAL) */
        !          1873: 
        !          1874: 
        !          1875: #if !defined(TRIO_MINIMAL)
        !          1876: /*
        !          1877:  * trio_xstring_equal_case_max
        !          1878:  */
        !          1879: TRIO_STRING_PUBLIC int
        !          1880: trio_xstring_equal_case_max
        !          1881: TRIO_ARGS3((self, max, other),
        !          1882:           trio_string_t *self,
        !          1883:           size_t max,
        !          1884:           TRIO_CONST char *other)
        !          1885: {
        !          1886:   assert(self);
        !          1887:   assert(other);
        !          1888: 
        !          1889:   return trio_equal_case_max(self->content, max, other);
        !          1890: }
        !          1891: #endif /* !defined(TRIO_MINIMAL) */
        !          1892: 
        !          1893: 
        !          1894: #if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE)
        !          1895: /*
        !          1896:  * trio_string_format_data_max
        !          1897:  */
        !          1898: TRIO_STRING_PUBLIC size_t
        !          1899: trio_string_format_date_max
        !          1900: TRIO_ARGS4((self, max, format, datetime),
        !          1901:           trio_string_t *self,
        !          1902:           size_t max,
        !          1903:           TRIO_CONST char *format,
        !          1904:           TRIO_CONST struct tm *datetime)
        !          1905: {
        !          1906:   assert(self);
        !          1907: 
        !          1908:   return trio_format_date_max(self->content, max, format, datetime);
        !          1909: }
        !          1910: #endif /* !defined(TRIO_MINIMAL) */
        !          1911: 
        !          1912: 
        !          1913: #if !defined(TRIO_MINIMAL)
        !          1914: /*
        !          1915:  * trio_string_index
        !          1916:  */
        !          1917: TRIO_STRING_PUBLIC char *
        !          1918: trio_string_index
        !          1919: TRIO_ARGS2((self, character),
        !          1920:           trio_string_t *self,
        !          1921:           int character)
        !          1922: {
        !          1923:   assert(self);
        !          1924: 
        !          1925:   return trio_index(self->content, character);
        !          1926: }
        !          1927: #endif /* !defined(TRIO_MINIMAL) */
        !          1928: 
        !          1929: 
        !          1930: #if !defined(TRIO_MINIMAL)
        !          1931: /*
        !          1932:  * trio_string_index_last
        !          1933:  */
        !          1934: TRIO_STRING_PUBLIC char *
        !          1935: trio_string_index_last
        !          1936: TRIO_ARGS2((self, character),
        !          1937:           trio_string_t *self,
        !          1938:           int character)
        !          1939: {
        !          1940:   assert(self);
        !          1941: 
        !          1942:   return trio_index_last(self->content, character);
        !          1943: }
        !          1944: #endif /* !defined(TRIO_MINIMAL) */
        !          1945: 
        !          1946: 
        !          1947: #if !defined(TRIO_MINIMAL)
        !          1948: /*
        !          1949:  * trio_string_length
        !          1950:  */
        !          1951: TRIO_STRING_PUBLIC int
        !          1952: trio_string_length
        !          1953: TRIO_ARGS1((self),
        !          1954:           trio_string_t *self)
        !          1955: {
        !          1956:   assert(self);
        !          1957: 
        !          1958:   if (self->length == 0)
        !          1959:     {
        !          1960:       self->length = trio_length(self->content);
        !          1961:     }
        !          1962:   return self->length;
        !          1963: }
        !          1964: #endif /* !defined(TRIO_MINIMAL) */
        !          1965: 
        !          1966: 
        !          1967: #if !defined(TRIO_MINIMAL)
        !          1968: /*
        !          1969:  * trio_string_lower
        !          1970:  */
        !          1971: TRIO_STRING_PUBLIC int
        !          1972: trio_string_lower
        !          1973: TRIO_ARGS1((self),
        !          1974:           trio_string_t *self)
        !          1975: {
        !          1976:   assert(self);
        !          1977: 
        !          1978:   return trio_lower(self->content);
        !          1979: }
        !          1980: #endif /* !defined(TRIO_MINIMAL) */
        !          1981: 
        !          1982: 
        !          1983: #if !defined(TRIO_MINIMAL)
        !          1984: /*
        !          1985:  * trio_string_match
        !          1986:  */
        !          1987: TRIO_STRING_PUBLIC int
        !          1988: trio_string_match
        !          1989: TRIO_ARGS2((self, other),
        !          1990:           trio_string_t *self,
        !          1991:           trio_string_t *other)
        !          1992: {
        !          1993:   assert(self);
        !          1994:   assert(other);
        !          1995: 
        !          1996:   return trio_match(self->content, other->content);
        !          1997: }
        !          1998: #endif /* !defined(TRIO_MINIMAL) */
        !          1999: 
        !          2000: 
        !          2001: #if !defined(TRIO_MINIMAL)
        !          2002: /*
        !          2003:  * trio_xstring_match
        !          2004:  */
        !          2005: TRIO_STRING_PUBLIC int
        !          2006: trio_xstring_match
        !          2007: TRIO_ARGS2((self, other),
        !          2008:           trio_string_t *self,
        !          2009:           TRIO_CONST char *other)
        !          2010: {
        !          2011:   assert(self);
        !          2012:   assert(other);
        !          2013: 
        !          2014:   return trio_match(self->content, other);
        !          2015: }
        !          2016: #endif /* !defined(TRIO_MINIMAL) */
        !          2017: 
        !          2018: 
        !          2019: #if !defined(TRIO_MINIMAL)
        !          2020: /*
        !          2021:  * trio_string_match_case
        !          2022:  */
        !          2023: TRIO_STRING_PUBLIC int
        !          2024: trio_string_match_case
        !          2025: TRIO_ARGS2((self, other),
        !          2026:           trio_string_t *self,
        !          2027:           trio_string_t *other)
        !          2028: {
        !          2029:   assert(self);
        !          2030:   assert(other);
        !          2031: 
        !          2032:   return trio_match_case(self->content, other->content);
        !          2033: }
        !          2034: #endif /* !defined(TRIO_MINIMAL) */
        !          2035: 
        !          2036: 
        !          2037: #if !defined(TRIO_MINIMAL)
        !          2038: /*
        !          2039:  * trio_xstring_match_case
        !          2040:  */
        !          2041: TRIO_STRING_PUBLIC int
        !          2042: trio_xstring_match_case
        !          2043: TRIO_ARGS2((self, other),
        !          2044:           trio_string_t *self,
        !          2045:           TRIO_CONST char *other)
        !          2046: {
        !          2047:   assert(self);
        !          2048:   assert(other);
        !          2049: 
        !          2050:   return trio_match_case(self->content, other);
        !          2051: }
        !          2052: #endif /* !defined(TRIO_MINIMAL) */
        !          2053: 
        !          2054: 
        !          2055: #if !defined(TRIO_MINIMAL)
        !          2056: /*
        !          2057:  * trio_string_substring
        !          2058:  */
        !          2059: TRIO_STRING_PUBLIC char *
        !          2060: trio_string_substring
        !          2061: TRIO_ARGS2((self, other),
        !          2062:           trio_string_t *self,
        !          2063:           trio_string_t *other)
        !          2064: {
        !          2065:   assert(self);
        !          2066:   assert(other);
        !          2067: 
        !          2068:   return trio_substring(self->content, other->content);
        !          2069: }
        !          2070: #endif /* !defined(TRIO_MINIMAL) */
        !          2071: 
        !          2072: 
        !          2073: #if !defined(TRIO_MINIMAL)
        !          2074: /*
        !          2075:  * trio_xstring_substring
        !          2076:  */
        !          2077: TRIO_STRING_PUBLIC char *
        !          2078: trio_xstring_substring
        !          2079: TRIO_ARGS2((self, other),
        !          2080:           trio_string_t *self,
        !          2081:           TRIO_CONST char *other)
        !          2082: {
        !          2083:   assert(self);
        !          2084:   assert(other);
        !          2085: 
        !          2086:   return trio_substring(self->content, other);
        !          2087: }
        !          2088: #endif /* !defined(TRIO_MINIMAL) */
        !          2089: 
        !          2090: 
        !          2091: #if !defined(TRIO_MINIMAL)
        !          2092: /*
        !          2093:  * trio_string_upper
        !          2094:  */
        !          2095: TRIO_STRING_PUBLIC int
        !          2096: trio_string_upper
        !          2097: TRIO_ARGS1((self),
        !          2098:           trio_string_t *self)
        !          2099: {
        !          2100:   assert(self);
        !          2101: 
        !          2102:   return trio_upper(self->content);
        !          2103: }
        !          2104: #endif /* !defined(TRIO_MINIMAL) */
        !          2105: 
        !          2106: /** @} End of DynamicStrings */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>