OpenDNSSEC-enforcer  1.3.8
/build/buildd/opendnssec-1.3.8/enforcer/ksm/string_util.c
Go to the documentation of this file.
00001 /*
00002  * $Id: string_util.c 3718 2010-08-10 21:17:18Z jakob $
00003  *
00004  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00029 /*++
00030  * Filename: string_util.c
00031  *
00032  * Description:
00033  *      String utility functions used by the whois programs.
00034 -*/
00035 
00036 #include "config.h"
00037 
00038 #include <assert.h>
00039 #include <ctype.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 
00044 #include "compat.h"
00045 
00046 #include "ksm/string_util.h"
00047 #include "ksm/message.h"
00048 #include "ksm/ksmdef.h"
00049 
00050 /*+
00051  * StrUncomment - Uncomment Line
00052  *
00053  * Description:
00054  *      Locates the first comment character in the line, and truncates the line
00055  *      at that point.  The comment character is hard-coded as the hash (#)
00056  *      character.
00057  *
00058  * Arguments:
00059  *      char* line (modified)
00060  *          Line to check.  If a comment introducer exists, it is replaced with
00061  *          a null character.  If the line is NULL, the routine is a no-op.
00062  *
00063  * Returns:
00064  *      void
00065 -*/
00066 
00067 void StrUncomment(char* line)
00068 {
00069     char *comment;      /* Pointer to first comment character */
00070 
00071     if (line && (comment = strstr(line, COMMENT_CHAR))) {
00072 
00073         /* comment points to character, or null if not found */
00074 
00075         *comment = '\0';
00076     }
00077 }
00078 
00079 
00080 
00081 /*+
00082  * StrWhitespace - Replace Whitespace
00083  *
00084  * Description:
00085  *      Replaces every whitespace characters with a space.  This conversion is
00086  *      usually done to simplify future processing.
00087  *
00088  * Arguments:
00089  *      char* line (modified)
00090  *          Line to modify.
00091  *
00092  * Returns:
00093  *      void
00094 -*/
00095 
00096 void StrWhitespace(char* line)
00097 {
00098     if (line) {
00099         while (*line) {
00100             if (isspace((int) *line)) {
00101                 *line = ' ';
00102             }
00103             ++line;
00104         }
00105     }
00106 }
00107 
00108 
00109 /*+
00110  * StrStrdup - Duplicate String
00111  *
00112  * Description:
00113  *      Wrapper for "strdup" that always returns, or exits the program (after
00114  *      outputting a message to stderr) if the string duplication fails.
00115  *
00116  * Arguments:
00117  *      const char* string (input)
00118  *          String to be duplicated.
00119  *
00120  * Returns:
00121  *      char*
00122  *          Pointer to duplicated string (guaranteed to be non-null).  The
00123  *          string should be freed with StrFree() - a macro wrapper for "free".
00124 -*/
00125 
00126 char* StrStrdup(const char* string)
00127 {
00128     char* duplicate = NULL; /* Pointer to the duplicated string */
00129 
00130     if (string) {
00131         duplicate = strdup(string);
00132         if (duplicate == NULL) {
00133                         MsgLog(KSM_STMTALLOC, "StrStrdup: Call to malloc() returned null - out of swap space?");
00134             fprintf(stderr, "StrStrdup: Call to malloc() returned null - out of swap space?");
00135             exit(1);
00136         }
00137     }
00138     else {
00139         duplicate = MemCalloc(1, 1);    /* Allocate a single zeroed byte */
00140     }
00141 
00142     return duplicate;
00143 }
00144 
00145 
00146 /*+
00147  * StrStrncpy - Copy String
00148  * StrStrncat - Concatenate String
00149  *
00150  * Description:
00151  *      Wrapper for "strncpy"/"strncat" that guarantees that:
00152  *
00153  *      (a) As much of the source string as possible is copied to the
00154  *          destination.
00155  *      (b) The destination string is terminated by a null byte (something not
00156  *          guaranteed by the standard functions).
00157  *
00158  *      Also, the function is void, unlike the standard library counterparts
00159  *      that return a pointer to the destination string.
00160  *
00161  * Arguments:
00162  *      char* dst (output)
00163  *          Destination string.  The final byte of this string will always be
00164  *          set to NULL.  If this argument is NULL, the routine is a no-op.
00165  *
00166  *      const char* src (input)
00167  *          Source string.  If NULL, the routine is a no-op (StrStrncat) or
00168  *          the destination is set to the empty string (StrStrncpy).
00169  *
00170  *      size_t dstlen (input)
00171  *          Total amount of space allocated for the destination, including the
00172  *          terminating null byte.  If this is zero, the routine is a no-op.
00173  *          Note that in the case of StrStrncat, this is the total amount of
00174  *          space IGNORING the current contents of "dst" - it is just the total
00175  *          space available to hold the entire resultant string.
00176 -*/
00177 
00178 void StrStrncpy(char* dst, const char* src, size_t dstlen)
00179 {
00180     if (dst && (dstlen > 0)) {
00181         if (src) {
00182             (void) strlcpy(dst, src, dstlen);
00183             /* dst[dstlen - 1] = '\0'; */
00184         }
00185         else {
00186             dst[0] = '\0';
00187         }
00188     }
00189 
00190     return;
00191 }
00192 
00193 void StrStrncat(char* dst, const char* src, size_t dstlen)
00194 {
00195     size_t  length;     /* Amount of space used in dst */
00196     size_t  remain;     /* Remaining space in dst */
00197 
00198     if (dst) {
00199         length = strlen(dst);
00200         remain = dstlen - length;
00201         if (remain > 1) {
00202 
00203             /* More space than just the trailing NULL */
00204 
00205             StrStrncpy(&dst[length], src, remain);
00206         }
00207     }
00208 
00209     return;
00210 }
00211 
00212 
00213 
00214 /*+
00215  * StrTrimR - Trim Right
00216  *
00217  * Description:
00218  *      Modifies a string by trimming white-space characters from the right of
00219  *      the string.  It does this by modifying the string, inserting a null
00220  *      character after the last non white-space character.
00221  *
00222  * Arguments:
00223  *      char *text (modified)
00224  *          Text to modify.  If this is NULL, the routine is a no-op.
00225  *
00226  * Returns:
00227  *      void
00228 -*/
00229 
00230 void StrTrimR(char *text)
00231 {
00232     if (text) {
00233 
00234         /* Work backwards through the string */
00235 
00236         int textlen = strlen(text);
00237         while (-- textlen >= 0) {
00238             if (! isspace((int) text[textlen])) {
00239                 text[textlen + 1] = '\0';
00240                 return;
00241             }
00242         }
00243 
00244         /* Get here if the entire string is white space */
00245 
00246         text[0] = '\0';
00247     }
00248     return;
00249 }
00250 
00251 
00252 
00253 /*+
00254  * StrTrimL - Trim Left
00255  *
00256  * Description:
00257  *      Searches a string and returns a pointer to the first non white-space
00258  *      character in it.
00259  *
00260  * Arguments:
00261  *      char* text (input)
00262  *          Text to search.
00263  *
00264  * Returns:
00265  *      char* 
00266  *          Pointer to first non white-space character in the string.  If the
00267  *          string is NULL, NULL is returned.  If the string is all white space,
00268  *          a pointer to the trailing null character is returned.
00269 -*/
00270 
00271 char* StrTrimL(char* text)
00272 {
00273     if (text) {
00274         while (*text && isspace((int) *text)) {
00275             ++text;
00276         }
00277     }
00278 
00279     return text;
00280 }
00281 
00282 
00283 /*+
00284  * StrTrim - Trim String
00285  *
00286  * Description:
00287  *      A combination of StrTrimL and StrTrimR, this routine modifies the passed
00288  *      string by inserting the null character after the last non-space in the
00289  *      string, then returning a pointer into the string to the first non
00290  *      white-space character.
00291  *
00292  * Arguments:
00293  *      char *text (modified)
00294  *          Text to be trimmed.  The text may be modified.
00295  *
00296  * Returns:
00297  *      char*
00298  *          Pointer into text of the first non white-space character.  If the
00299  *          input string is NULL, NULL is returned.
00300 -*/
00301 
00302 char* StrTrim(char* text)
00303 {
00304     StrTrimR(text);
00305     return StrTrimL(text);
00306 }
00307 
00308 
00309 /*+
00310  * StrToLower - Convert to Lower Case
00311  *
00312  * Description:
00313  *      Converts the passed string to lowercase characters.  As a side-effect it
00314  *      also returns the length of the string.
00315  *
00316  * Arguments:
00317  *      char *text (modified)
00318  *          String to be modified.  If NULL, this routine is a no-op.
00319  *
00320  * Returns:
00321  *      size_y
00322  *          Length of the string.
00323 -*/
00324 
00325 size_t StrToLower(char* string)
00326 {
00327     char* ptr = string;
00328     if (ptr) {
00329         while (*ptr) {
00330             *ptr = tolower((int) *ptr);
00331             ++ptr;
00332         }
00333     }
00334 
00335     return (size_t) (ptr - string);
00336 }
00337 
00338 
00339 /*+
00340  * StrToUpper - Convert to Upper Case
00341  *
00342  * Description:
00343  *      Converts the passed string to uppercase characters.  As a side-effect it
00344  *      also returns the length of the string.
00345  *
00346  * Arguments:
00347  *      char *text (modified)
00348  *          String to be modified.  If NULL, this routine is a no-op.
00349  *
00350  * Returns:
00351  *      size_t
00352  *          Length of the string.
00353 -*/
00354 
00355 size_t StrToUpper(char* string)
00356 {
00357     char* ptr = string;
00358     if (ptr) {
00359         while (*ptr) {
00360             *ptr = toupper((int) *ptr);
00361             ++ptr;
00362         }
00363     }
00364 
00365     return (size_t) (ptr - string);
00366 }
00367 
00368 
00369 
00370 /*+
00371  * StrReplaceChar - Replace Character - Null-Terminated String
00372  * StrReplaceCharN - Replace Character - Length Given
00373  *
00374  * Description:
00375  *      Replaces all occurrences of a given character in a string by the given
00376  *      character.
00377  *
00378  *      StrReplaceCharN is generally used where the string may contain embedded
00379  *      null characters in order to remove them.
00380  *
00381  * Arguments:
00382  *      char* string (modified)
00383  *          String in which the replacement is to take place.
00384  *
00385  *      size_t len (input, StrReplaceCharN only)
00386  *          Lenght of input string.
00387  *
00388  *      char search (input)
00389  *          Character to search for.
00390  *
00391  *      char replace (input)
00392  *          Replacement chaaracter.
00393  *
00394  * Returns:
00395  *      size_t
00396  *          Number of replacements.
00397 -*/
00398 
00399 size_t StrReplaceCharN(char* string, size_t len, char search, char replace)
00400 {
00401     size_t count = 0;   /* Replacement count */
00402     size_t i;           /* Loop counter */
00403 
00404     if (string) {
00405         for (i = 0; i < len; ++i) {
00406             if (string[i] == search) {
00407                 string[i] = replace;
00408                 ++count;
00409             }
00410         }
00411     }
00412     return count;
00413 }
00414 
00415 size_t StrReplaceChar(char* string, char search, char replace)
00416 {
00417     size_t count = 0;   /* Replacement count */
00418 
00419     if (string) {
00420         count = StrReplaceCharN(string, strlen(string), search, replace);
00421     }
00422     return count;
00423 }
00424 
00425 
00426 
00427 /*+
00428  * StrTrimmedLength
00429  *
00430  * Description:
00431  *      Searches the string and returns the length of the string less leading
00432  *      and trailing spaces.  Essentially, this will be the result of a call to
00433  *      strlen() after the string has been passed through StrTrim().
00434  *
00435  * Arguments:
00436  *      const char* string (input)
00437  *          String to search.
00438  *
00439  * Returns:
00440  *      size_t
00441  *          Size of the string.
00442 -*/
00443 
00444 size_t StrTrimmedLength(const char* string)
00445 {
00446     size_t  length = 0;     /* Length of trimmed string */
00447     size_t  in_length;      /* Length of input string */
00448     size_t  first_char;     /* Position of first non-space character */
00449     size_t  last_char;      /* Position of last non-space character */
00450 
00451     if (string) {
00452         in_length = strlen(string);
00453 
00454         /*
00455          * Get offset of first non-space character.  If the string does not
00456          * contain any such characters, first_char will equal "length".
00457          */
00458 
00459         first_char = 0;
00460         while (first_char < in_length) {
00461             if (! isspace((int) string[first_char])) {
00462                 break;
00463             }
00464             ++first_char;
00465         }
00466 
00467         if (first_char < in_length) {
00468 
00469             /*
00470              * Must be a printable character, so find the offset of the last
00471              * such character.
00472              */
00473 
00474             last_char = in_length - 1;
00475             while (isspace((int) string[last_char])) {
00476                 --last_char;
00477             }
00478 
00479             /* ... and work out the length */
00480 
00481             length = last_char - first_char + 1;
00482             assert(length > 0);
00483         }
00484 
00485         /* No "else" - length is set to zero on enty */
00486     }
00487 
00488     return length;
00489 }