1 Star 0 Fork 9

yang/libxml2_backup

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

搜索帮助