00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Joe Drew 00008 * Side Effects Software Inc 00009 * 123 Front Street West, Suite 1401 00010 * Toronto, Ontario 00011 * Canada M5J 2M2 00012 * 416-504-9876 00013 * 00014 * NAME: SYS_String.h (SYS Library, C++) 00015 * 00016 * COMMENTS: 00017 * System-independent string manipulation functions. 00018 */ 00019 00020 #ifndef __SYS_String__ 00021 #define __SYS_String__ 00022 00023 #include "SYS_API.h" 00024 00025 #include <ctype.h> 00026 #include <string.h> 00027 00028 #if defined(GAMEOS) 00029 static char * 00030 memccpy(char *dest, const char *src, char find, int size) 00031 { 00032 int i; 00033 for (i = 0; i < size; i++) 00034 { 00035 if (*src == find) return dest; 00036 *dest++ = *src++; 00037 } 00038 return 0; 00039 } 00040 #endif 00041 00042 /// A standard name for a strtok that doesn't maintain state between calls. 00043 /// This version is thus both reentrant and threadsafe. 00044 /// SYSstrtok parses a string into a sequence of tokens. On the first call to 00045 /// SYSstrtok, the string to be parsed must be specified as the parameter 00046 /// 'string'. This parameter *will be modified* (destroying your copy). 00047 /// 'delimit' specifies an array of single characters that will be used 00048 /// as delimiters. 00049 /// 'context' is a char * variable used internally by SYSstrtok to maintain 00050 /// context between calls. Subsequent calls must specify the same unchanged 00051 /// context variable as the first call. 00052 /// To use SYSstrtok, on the first call first pass in your string as the 00053 /// parameter 'string'; on subsequent calls, pass it in as NULL. 00054 /// SYSstrtok returns non-empty strings pointing to the first non-delimiter 00055 /// character of each token, or NULL if no further tokens are available. 00056 /// Example: 00057 /// \code 00058 /// char *string = strdup(getString()); 00059 /// char *strptr = string; 00060 /// char *context; 00061 /// char *token = SYSstrtok(string, MY_DELIMITERS, &context); 00062 /// while (token) 00063 /// { 00064 /// do_some_stuff(); 00065 /// SYSstrtok(NULL, MY_DELIMITERS, &context); 00066 /// } 00067 /// free(strptr); 00068 /// \endcode 00069 inline char * 00070 SYSstrtok(char *string, const char *delimit, char **context) 00071 { 00072 #ifdef LINUX 00073 return strtok_r(string, delimit, context); 00074 #else 00075 // MSVC 2003 doesn't have strtok_r. 2005 has strtok_s, which is the same 00076 // as strtok_r. Until we upgrade, use this C version of strtok_r. 00077 if (string == NULL) 00078 { 00079 string = *context; 00080 } 00081 00082 // Find and skip any leading delimiters. 00083 string += strspn(string, delimit); 00084 00085 // There are only delimiters (or no text at all), so we've reached the end 00086 // of the string. 00087 if (*string == '\0') 00088 { 00089 *context = string; 00090 return NULL; 00091 } 00092 00093 // String now points at a token. 00094 char *token = string; 00095 00096 // Find the end of the token. 00097 string = strpbrk(token, delimit); 00098 if (!string) 00099 { 00100 // This token is at the end of the string. Set the context to point at 00101 // the end of the string so on the next call, we'll return NULL. 00102 *context = strchr(token, '\0'); 00103 } 00104 else 00105 { 00106 // This is a token somewhere in the string. Set the found delimiter to 00107 // zero and initialize the context to the next character. 00108 *string = '\0'; 00109 *context = string + 1; 00110 } 00111 00112 return token; 00113 #endif 00114 } 00115 00116 /// The semantics for strncpy() leave a little to be desired 00117 /// - If the buffer limit is hit, the string isn't guaranteed to be null 00118 /// terminated. 00119 /// - If the buffer limit isn't hit, the entire remainder of the string is 00120 /// filled with nulls (which can be costly with large buffers). 00121 /// The following implements the strlcpy() function from OpenBSD. The function 00122 /// is very similar to strncpy() but 00123 /// The return code is the length of the src string 00124 /// The resulting string is always null terminated (unless size == 0) 00125 /// The remaining buffer is not touched 00126 /// It's possible to check for errors by testing rcode >= size. 00127 inline size_t 00128 SYSstrlcpy(char *dest, const char *src, size_t size) 00129 { 00130 char *end; 00131 end = (char *)::memccpy(dest, src, 0, size); 00132 if (end) 00133 { 00134 *end = 0; 00135 return end - dest - 1; 00136 } 00137 // No null terminator found in the first size-1 bytes 00138 if (size) 00139 dest[size-1] = 0; 00140 return size + ::strlen(src+size); 00141 } 00142 00143 /// The following implements the strlcpy() function from OpenBSD. The 00144 /// differences between strlcpy() and strncpy() are: 00145 /// - The buffer will not be filled with null 00146 /// - The size passed in is the full length of the buffer (not 00147 /// remaining length) 00148 /// - The dest will always be null terminated (unless it is already larger 00149 /// than the size passed in) 00150 /// The function returns strln(src) + SYSmin(size, strlen(dest)) 00151 /// If rcode >= size, truncation occurred 00152 00153 inline size_t 00154 SYSstrlcat(char *dest, const char *src, size_t size) 00155 { 00156 char *end; 00157 size_t dlen; 00158 00159 // Find the length of the dest buffer. Only check for a null within the 00160 // allocated space of the buffer (i.e. we can't use strlen()). 00161 for (dlen = 0; dlen < size; dlen++) 00162 if (!dest[dlen]) 00163 break; 00164 if (dlen == size) 00165 return size + ::strlen(src); // Not enough space left 00166 // Now, copy the source over 00167 end = (char *)::memccpy(dest+dlen, src, 0, size-dlen); 00168 if (end) 00169 { 00170 *end = 0; 00171 return end - dest - 1; 00172 } 00173 if (size) 00174 dest[size-1] = 0; 00175 return dlen + ::strlen(src); 00176 } 00177 00178 inline bool 00179 SYSisspace(char c) 00180 { 00181 // cast to unsigned so that we don't pass negative numbers to isspace 00182 // or else it will assert on Windows 00183 return isspace((unsigned char)c); 00184 } 00185 00186 inline bool 00187 SYSisspace(unsigned char c) 00188 { 00189 return isspace(c); 00190 } 00191 00192 inline bool 00193 SYSisspace(int c) 00194 { 00195 if (c < 0 || c > 127) 00196 return false; 00197 else 00198 return isspace(c); 00199 } 00200 00201 #endif
1.5.9