📄 triostr.c
字号:
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -