📄 triostr.c
字号:
/************************************************************************* * * $Id: triostr.c,v 1.30 2005/11/26 14:47:54 breese Exp $ * * 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 */#if defined(HAVE_CONFIG_H)# include <config.h>#endif#include <assert.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "triodef.h"#include "triostr.h"#if defined(TRIO_FUNC_TO_LONG_DOUBLE)# define USE_MATH#endif#if defined(USE_MATH)# include <math.h>#endif/************************************************************************* * Definitions */#if !defined(TRIO_PUBLIC_STRING)# define TRIO_PUBLIC_STRING TRIO_PUBLIC#endif#if !defined(TRIO_PRIVATE_STRING)# define TRIO_PRIVATE_STRING 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#if defined(USE_MATH)# if defined(PREDEF_STANDARD_C99)# if defined(TRIO_COMPILER_DECC)# if (TRIO_COMPILER_DECC - 0 > 80000000)/* * The OSF/1 runtime that comes with the DECC compiler does not support * hexfloats conversion. */# define USE_STRTOD# define USE_STRTOF# endif# else# define USE_STRTOD# define USE_STRTOF# endif# else# if defined(TRIO_COMPILER_VISUALC)# define USE_STRTOD# endif#endif#endif#if defined(TRIO_PLATFORM_UNIX)# if defined(PREDEF_STANDARD_UNIX95)# define USE_STRCASECMP# define USE_STRNCASECMP# endif# 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#endif#if defined(TRIO_PLATFORM_WIN32)# define USE_STRCASECMP# define strcasecmp(x,y) strcmpi(x,y)#endif#if !(defined(TRIO_PLATFORM_SUNOS))# define USE_TOLOWER# define USE_TOUPPER#endif#if defined(USE_MATH)# if !defined(HAVE_POWL)# if defined(PREDEF_STANDARD_C99) \ || defined(PREDEF_STANDARD_UNIX03)# define HAVE_POWL# else# if defined(TRIO_COMPILER_VISUALC)# if defined(powl)# define HAVE_POWL# endif# endif# endif# endif#endif#if defined(HAVE_POWL)# define trio_powl(x,y) powl((x),(y))#else# define trio_powl(x,y) pow((double)(x),(double)(y))#endif#if defined(TRIO_FUNC_TO_UPPER) \ || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \ || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \ || defined(TRIO_FUNC_MATCH) \ || defined(TRIO_FUNC_TO_LONG_DOUBLE) \ || defined(TRIO_FUNC_UPPER)# define TRIO_FUNC_INTERNAL_TO_UPPER#endif/************************************************************************* * Structures */struct _trio_string_t{ char *content; size_t length; size_t allocated;};/************************************************************************* * Constants */#if !defined(TRIO_EMBED_STRING)static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.30 2005/11/26 14:47:54 breese Exp $";#endif/************************************************************************* * Static String Functions */#if defined(TRIO_DOCUMENTATION)# include "doc/doc_static.h"#endif/** @addtogroup StaticStrings @{*//* * internal_duplicate_max */#if defined(TRIO_FUNC_DUPLICATE) \ || defined(TRIO_FUNC_DUPLICATE_MAX) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE)TRIO_PRIVATE_STRING char *internal_duplicate_maxTRIO_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;}#endif/* * internal_string_alloc */#if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE)TRIO_PRIVATE_STRING trio_string_t *internal_string_alloc(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;}#endif/* * internal_string_grow * * The size of the string will be increased by 'delta' characters. If * 'delta' is zero, the size will be doubled. */#if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND_CHAR)TRIO_PRIVATE_STRING BOOLEAN_Tinternal_string_growTRIO_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;}#endif/* * internal_string_grow_to * * 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). */#if defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND)TRIO_PRIVATE_STRING BOOLEAN_Tinternal_string_grow_toTRIO_ARGS2((self, length), trio_string_t *self, size_t length){ length++; /* Room for terminating zero */ return (self->allocated < length) ? internal_string_grow(self, length - self->allocated) : TRUE;}#endif#if defined(TRIO_FUNC_INTERNAL_TO_UPPER)TRIO_PRIVATE_STRING TRIO_INLINE intinternal_to_upperTRIO_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}#endif/** Create new string. @param size Size of new string. @return Pointer to string, or NULL if allocation failed.*/#if defined(TRIO_FUNC_CREATE)TRIO_PUBLIC_STRING char *trio_createTRIO_ARGS1((size), size_t size){ return (char *)TRIO_MALLOC(size);}#endif/** Destroy string. @param string String to be freed.*/#if defined(TRIO_FUNC_DESTROY)TRIO_PUBLIC_STRING voidtrio_destroyTRIO_ARGS1((string), char *string){ if (string) { TRIO_FREE(string); }}#endif/** Count the number of characters in a string. @param string String to measure. @return Number of characters in @p string.*/#if defined(TRIO_FUNC_LENGTH)TRIO_PUBLIC_STRING size_ttrio_lengthTRIO_ARGS1((string), TRIO_CONST char *string){ return strlen(string);}#endif/** 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.*/#if defined(TRIO_FUNC_APPEND)TRIO_PUBLIC_STRING inttrio_appendTRIO_ARGS2((target, source), char *target, TRIO_CONST char *source){ assert(target); assert(source); return (strcat(target, source) != NULL);}#endif/** 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.*/#if defined(TRIO_FUNC_APPEND_MAX)TRIO_PUBLIC_STRING inttrio_append_maxTRIO_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/** 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.*/#if defined(TRIO_FUNC_CONTAINS)TRIO_PUBLIC_STRING inttrio_containsTRIO_ARGS2((string, substring), TRIO_CONST char *string, TRIO_CONST char *substring){ assert(string); assert(substring); return (0 != strstr(string, substring));}#endif/** 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.*/#if defined(TRIO_FUNC_COPY)TRIO_PUBLIC_STRING inttrio_copyTRIO_ARGS2((target, source), char *target, TRIO_CONST char *source){ assert(target); assert(source); (void)strcpy(target, source); return TRUE;}#endif/** 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.*/#if defined(TRIO_FUNC_COPY_MAX)TRIO_PUBLIC_STRING inttrio_copy_maxTRIO_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;}#endif/** Duplicate @p source. @param source Source string. @return A copy of the @p source string. @post @p target will be zero terminated.*/#if defined(TRIO_FUNC_DUPLICATE)TRIO_PUBLIC_STRING char *trio_duplicateTRIO_ARGS1((source), TRIO_CONST char *source){ return internal_duplicate_max(source, trio_length(source));}#endif/** 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.*/#if defined(TRIO_FUNC_DUPLICATE_MAX)TRIO_PUBLIC_STRING char *trio_duplicate_maxTRIO_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 internal_duplicate_max(source, length);}#endif/** 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.*/#if defined(TRIO_FUNC_EQUAL)TRIO_PUBLIC_STRING inttrio_equalTRIO_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 (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; } return ((*first == NIL) && (*second == NIL));# endif } return FALSE;}#endif/** 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.*/#if defined(TRIO_FUNC_EQUAL_CASE)TRIO_PUBLIC_STRING inttrio_equal_caseTRIO_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;}#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-sensitive comparison.*/#if defined(TRIO_FUNC_EQUAL_CASE_MAX)TRIO_PUBLIC_STRING inttrio_equal_case_maxTRIO_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/** 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.*/#if defined(TRIO_FUNC_EQUAL_LOCALE)TRIO_PUBLIC_STRING inttrio_equal_localeTRIO_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}#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.*/#if defined(TRIO_FUNC_EQUAL_MAX)TRIO_PUBLIC_STRING inttrio_equal_maxTRIO_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 (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; cnt++; } return ((cnt == max) || ((*first == NIL) && (*second == NIL)));# endif } return FALSE;}#endif/** Provide a textual description of an error code (errno). @param error_number Error number. @return Textual description of @p error_number.*/#if defined(TRIO_FUNC_ERROR)TRIO_PUBLIC_STRING TRIO_CONST char *trio_errorTRIO_ARGS1((error_number), int error_number){# if defined(USE_STRERROR) return strerror(error_number);# else# if defined(USE_SYS_ERRLIST)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -