• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_string.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026   ink_string.h
00027 
00028   String and text processing routines for libts
00029 
00030  ****************************************************************************/
00031 
00032 #ifndef _ink_string_h_
00033 #define _ink_string_h_
00034 
00035 #include <stdio.h>
00036 #include <memory.h>
00037 #include <strings.h>
00038 
00039 #include "ink_assert.h"
00040 #include "ink_error.h"
00041 #include "ParseRules.h"
00042 #include "ink_apidefs.h"
00043 
00044 
00045 /*===========================================================================*
00046 
00047                             Function Prototypes
00048 
00049  *===========================================================================*/
00050 /* these are supposed to be fast */
00051 
00052 inkcoreapi char *ink_memcpy_until_char(char *dst, char *src, unsigned int n, unsigned char c);
00053 inkcoreapi char *ink_strncpy(char *dest, const char *src, int n);
00054 inkcoreapi char *ink_strncat(char *dest, const char *src, int n);
00055 inkcoreapi char *ink_string_concatenate_strings(char *dest, ...);
00056 inkcoreapi char *ink_string_concatenate_strings_n(char *dest, int n, ...);
00057 inkcoreapi char *ink_string_append(char *dest, char *src, int n);
00058 
00059 /*
00060  * Copy src to string dst of size siz.  At most siz-1 characters
00061  * will be copied.  Always NUL terminates (unless siz == 0).
00062  * Returns strlen(src); if retval >= siz, truncation occurred.
00063  */
00064 #if HAVE_STRLCPY
00065 #define  ink_strlcpy strlcpy
00066 #else
00067 size_t ink_strlcpy(char *dst, const char *str, size_t siz);
00068 #endif
00069 /*
00070  * Appends src to string dst of size siz (unlike strncat, siz is the
00071  * full size of dst, not space left).  At most siz-1 characters
00072  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
00073  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
00074  * If retval >= siz, truncation occurred.
00075  */
00076 #if HAVE_STRLCAT
00077 #define  ink_strlcat strlcat
00078 #else
00079 size_t ink_strlcat(char *dst, const char *str, size_t siz);
00080 #endif
00081 
00082 inkcoreapi int ink_strcasecmp(const char *a, const char *b);
00083 inkcoreapi int ink_strncasecmp(const char *a, const char *b, unsigned int max);
00084 
00085 /* Convert from UTF-8 to latin-1/iso-8859-1.  This can be lossy. */
00086 void ink_utf8_to_latin1(const char *in, int inlen, char *out, int *outlen);
00087 
00088 /*===========================================================================*
00089 
00090                              Inline Functions
00091 
00092  *===========================================================================*/
00093 
00094 
00095 // inline int ptr_len_cmp(const char* p1, int l1, const char* p2, int l2)
00096 //
00097 //     strcmp() functionality for two ptr length pairs
00098 //
00099 inline int
00100 ptr_len_cmp(const char *p1, int l1, const char *p2, int l2)
00101 {
00102   if (l1 == l2) {
00103     return memcmp(p1, p2, l1);
00104   } else if (l1 < l2) {
00105     return -1;
00106   } else {
00107     return 1;
00108   }
00109 }
00110 
00111 // inline int ptr_len_cmp(const char* p1, int l1, const char* p2, int l2)
00112 //
00113 //     strcasecmp() functionality for two ptr length pairs
00114 //
00115 inline int
00116 ptr_len_casecmp(const char *p1, int l1, const char *p2, int l2)
00117 {
00118   if (l1 < l2) {
00119     return -1;
00120   } else if (l1 > l2) {
00121     return 1;
00122   }
00123 
00124   while (l1) {
00125     char p1c = ParseRules::ink_tolower(*p1);
00126     char p2c = ParseRules::ink_tolower(*p2);
00127 
00128     if (p1c != p2c) {
00129       if (p1c > p2c) {
00130         return 1;
00131       } else {
00132         return -1;
00133       }
00134     }
00135 
00136     p1++;
00137     p2++;
00138     l1--;
00139   }
00140 
00141   return 0;
00142 }
00143 
00144 // inline const char* ptr_len_str(const char* p1, int l1, const char* str)
00145 //
00146 //   strstr() like functionality for the ptr, len pairs
00147 //
00148 inline const char *
00149 ptr_len_str(const char *p1, int l1, const char *str)
00150 {
00151 
00152   if (str && str[0]) {
00153     int str_index = 0;
00154     const char *match_start = NULL;
00155 
00156     while (l1 > 0) {
00157       if (*p1 == str[str_index]) {
00158 
00159         // If this is the start of a match,
00160         //    record it;
00161         if (str_index == 0) {
00162           match_start = p1;
00163         }
00164         // Check to see if we are finished;
00165         str_index++;
00166         if (str[str_index] == '\0') {
00167           return match_start;
00168         }
00169       } else if (str_index > 0) {
00170         l1 += (p1 - match_start);
00171         p1 = match_start;
00172         str_index = 0;
00173       }
00174 
00175       p1++;
00176       l1--;
00177     }
00178   }
00179   return NULL;
00180 }
00181 
00182 // int ptr_len_ncmp(const char* p1, int l1, const char* str, int n) {
00183 //
00184 //    strncmp like functionality for comparing a ptr,len pair with
00185 //       a null terminated string for n chars
00186 //
00187 inline int
00188 ptr_len_ncmp(const char *p1, int l1, const char *str, int n)
00189 {
00190 
00191 
00192   while (l1 > 0 && n > 0) {
00193     if (*str == '\0') {
00194       return 1;
00195     }
00196 
00197     char p1c = *p1;
00198     char strc = *str;
00199 
00200     if (p1c != strc) {
00201       if (p1c > strc) {
00202         return 1;
00203       } else if (p1c < strc) {
00204         return -1;
00205       }
00206     }
00207 
00208     p1++;
00209     l1--;
00210     n--;
00211     str++;
00212   }
00213 
00214   // If we've scanned our nchars, the match
00215   //   otherwise we're here because str is longer
00216   //   than p1
00217 
00218   if (n == 0) {
00219     return 0;
00220   } else {
00221     return -1;
00222   }
00223 }
00224 
00225 
00226 // int ptr_len_ncasecmp(const char* p1, int l1, const char* str, int n) {
00227 //
00228 //    strncasecmp like functionality for comparing a ptr,len pair with
00229 //       a null terminated string for n chars
00230 //
00231 inline int
00232 ptr_len_ncasecmp(const char *p1, int l1, const char *str, int n)
00233 {
00234 
00235 
00236   while (l1 > 0 && n > 0) {
00237     if (*str == '\0') {
00238       return 1;
00239     }
00240 
00241     char p1c = ParseRules::ink_tolower(*p1);
00242     char strc = ParseRules::ink_tolower(*str);
00243 
00244     if (p1c != strc) {
00245       if (p1c > strc) {
00246         return 1;
00247       } else if (p1c < strc) {
00248         return -1;
00249       }
00250     }
00251 
00252     p1++;
00253     l1--;
00254     n--;
00255     str++;
00256   }
00257 
00258   // If we've scanned our nchars, the match
00259   //   otherwise we're here because str is longer
00260   //   than p1
00261 
00262   if (n == 0) {
00263     return 0;
00264   } else {
00265     return -1;
00266   }
00267 }
00268 
00269 // int ptr_len_casecmp(const char* p1, int l1, const char* str) {
00270 //
00271 //    strcasecmp like functionality for comparing a ptr,len pair with
00272 //       a null terminated string
00273 //
00274 inline int
00275 ptr_len_casecmp(const char *p1, int l1, const char *str)
00276 {
00277 
00278   while (l1 > 0) {
00279     if (*str == '\0') {
00280       return 1;
00281     }
00282 
00283     char p1c = ParseRules::ink_tolower(*p1);
00284     char strc = ParseRules::ink_tolower(*str);
00285 
00286     if (p1c != strc) {
00287       if (p1c > strc) {
00288         return 1;
00289       } else if (p1c < strc) {
00290         return -1;
00291       }
00292     }
00293 
00294     p1++;
00295     l1--;
00296     str++;
00297   }
00298 
00299   // Since we're out of characters in p1
00300   //   str needs to be finished for the strings
00301   //   to get equal
00302   if (*str == '\0') {
00303     return 0;
00304   } else {
00305     return -1;
00306   }
00307 }
00308 
00309 
00310 // int ptr_len_cmp(const char* p1, int l1, const char* str) {
00311 //
00312 //    strcmp like functionality for comparing a ptr,len pair with
00313 //       a null terminated string
00314 //
00315 inline int
00316 ptr_len_cmp(const char *p1, int l1, const char *str)
00317 {
00318 
00319   while (l1 > 0) {
00320     if (*str == '\0') {
00321       return 1;
00322     }
00323 
00324     char p1c = *p1;
00325     char strc = *str;
00326 
00327     if (p1c != strc) {
00328       if (p1c > strc) {
00329         return 1;
00330       } else if (p1c < strc) {
00331         return -1;
00332       }
00333     }
00334 
00335     p1++;
00336     l1--;
00337     str++;
00338   }
00339 
00340   // Since we're out of characters in p1
00341   //   str needs to be finished for the strings
00342   //   to get equal
00343   if (*str == '\0') {
00344     return 0;
00345   } else {
00346     return -1;
00347   }
00348 }
00349 
00350 // char* ptr_len_pbrk(const char* p1, int l1, const char* str)
00351 //
00352 //   strpbrk() like functionality for ptr & len pair strings
00353 //
00354 inline char *
00355 ptr_len_pbrk(const char *p1, int l1, const char *str)
00356 {
00357   while (l1 > 0) {
00358     const char *str_cur = str;
00359 
00360     while (*str_cur != '\0') {
00361       if (*p1 == *str_cur) {
00362         return (char *) p1;
00363       }
00364       str_cur++;
00365     }
00366 
00367     p1++;
00368     l1--;
00369   }
00370 
00371   return NULL;
00372 }
00373 
00374 // Specialized "itoa", that is optimized for small integers, and use snprintf() otherwise.
00375 // On error, we'll return 0, and nothing is written to the buffer.
00376 // TODO: Do these really need to be inline?
00377 inline int
00378 ink_small_itoa(int val, char* buf, int buf_len)
00379 {
00380   ink_assert(buf_len > 5);
00381   ink_assert((val >= 0) && (val < 100000));
00382 
00383   if (val < 10) {               // 0 - 9
00384     buf[0] = '0' + val;
00385     return 1;
00386   } else if (val < 100) {       // 10 - 99
00387     buf[1] = '0' + (val % 10);
00388     val /= 10;
00389     buf[0] = '0' + (val % 10);
00390     return 2;
00391   } else if (val < 1000) {      // 100 - 999
00392     buf[2] = '0' + (val % 10);
00393     val /= 10;
00394     buf[1] = '0' + (val % 10);
00395     val /= 10;
00396     buf[0] = '0' + (val % 10);
00397     return 3;
00398   } else if (val < 10000) {     // 1000 - 9999
00399     buf[3] = '0' + (val % 10);
00400     val /= 10;
00401     buf[2] = '0' + (val % 10);
00402     val /= 10;
00403     buf[1] = '0' + (val % 10);
00404     val /= 10;
00405     buf[0] = '0' + (val % 10);
00406     return 4;
00407   } else {                      // 10000 - 99999
00408     buf[4] = '0' + (val % 10);
00409     val /= 10;
00410     buf[3] = '0' + (val % 10);
00411     val /= 10;
00412     buf[2] = '0' + (val % 10);
00413     val /= 10;
00414     buf[1] = '0' + (val % 10);
00415     val /= 10;
00416     buf[0] = '0' + (val % 10);
00417     return 5;
00418   }
00419 }
00420 
00421 inline int
00422 ink_fast_itoa(int32_t val, char* buf, int buf_len)
00423 {
00424   if ((val < 0) || (val > 99999)) {
00425     int ret = snprintf(buf, buf_len, "%d", val);
00426 
00427     return (ret >= 0 ? ret : 0);
00428   }
00429 
00430   return ink_small_itoa((int)val, buf, buf_len);
00431 }
00432 
00433 inline int
00434 ink_fast_uitoa(uint32_t val, char* buf, int buf_len)
00435 {
00436   if (val > 99999) {
00437     int ret = snprintf(buf, buf_len, "%u", val);
00438 
00439     return (ret >= 0 ? ret : 0);
00440   }
00441 
00442   return ink_small_itoa((int)val, buf, buf_len);
00443 }
00444 
00445 inline int
00446 ink_fast_ltoa(int64_t val, char* buf, int buf_len)
00447 {
00448   if ((val < 0) || (val > 99999)) {
00449     int ret = snprintf(buf, buf_len, "%" PRId64 "", val);
00450 
00451     return (ret >= 0 ? ret : 0);
00452   }
00453 
00454   return ink_small_itoa((int)val, buf, buf_len);
00455 }
00456 
00457 #endif

Generated by  doxygen 1.7.1