OpenDNSSEC-enforcer  1.4.9
string_util.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*++
28  * Filename: string_util.c
29  *
30  * Description:
31  * String utility functions used by the whois programs.
32 -*/
33 
34 #include "config.h"
35 
36 #include <assert.h>
37 #include <ctype.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #include "compat.h"
43 
44 #include "ksm/string_util.h"
45 #include "ksm/message.h"
46 #include "ksm/ksmdef.h"
47 
48 /*+
49  * StrUncomment - Uncomment Line
50  *
51  * Description:
52  * Locates the first comment character in the line, and truncates the line
53  * at that point. The comment character is hard-coded as the hash (#)
54  * character.
55  *
56  * Arguments:
57  * char* line (modified)
58  * Line to check. If a comment introducer exists, it is replaced with
59  * a null character. If the line is NULL, the routine is a no-op.
60  *
61  * Returns:
62  * void
63 -*/
64 
65 void StrUncomment(char* line)
66 {
67  char *comment; /* Pointer to first comment character */
68 
69  if (line && (comment = strstr(line, COMMENT_CHAR))) {
70 
71  /* comment points to character, or null if not found */
72 
73  *comment = '\0';
74  }
75 }
76 
77 
78 
79 /*+
80  * StrWhitespace - Replace Whitespace
81  *
82  * Description:
83  * Replaces every whitespace characters with a space. This conversion is
84  * usually done to simplify future processing.
85  *
86  * Arguments:
87  * char* line (modified)
88  * Line to modify.
89  *
90  * Returns:
91  * void
92 -*/
93 
94 void StrWhitespace(char* line)
95 {
96  if (line) {
97  while (*line) {
98  if (isspace((int) *line)) {
99  *line = ' ';
100  }
101  ++line;
102  }
103  }
104 }
105 
106 
107 /*+
108  * StrStrdup - Duplicate String
109  *
110  * Description:
111  * Wrapper for "strdup" that always returns, or exits the program (after
112  * outputting a message to stderr) if the string duplication fails.
113  *
114  * Arguments:
115  * const char* string (input)
116  * String to be duplicated.
117  *
118  * Returns:
119  * char*
120  * Pointer to duplicated string (guaranteed to be non-null). The
121  * string should be freed with StrFree() - a macro wrapper for "free".
122 -*/
123 
124 char* StrStrdup(const char* string)
125 {
126  char* duplicate = NULL; /* Pointer to the duplicated string */
127 
128  if (string) {
129  duplicate = strdup(string);
130  if (duplicate == NULL) {
131  MsgLog(KSM_STMTALLOC, "StrStrdup: Call to malloc() returned null - out of swap space?");
132  fprintf(stderr, "StrStrdup: Call to malloc() returned null - out of swap space?");
133  exit(1);
134  }
135  }
136  else {
137  duplicate = MemCalloc(1, 1); /* Allocate a single zeroed byte */
138  }
139 
140  return duplicate;
141 }
142 
143 
144 /*+
145  * StrStrncpy - Copy String
146  * StrStrncat - Concatenate String
147  *
148  * Description:
149  * Wrapper for "strncpy"/"strncat" that guarantees that:
150  *
151  * (a) As much of the source string as possible is copied to the
152  * destination.
153  * (b) The destination string is terminated by a null byte (something not
154  * guaranteed by the standard functions).
155  *
156  * Also, the function is void, unlike the standard library counterparts
157  * that return a pointer to the destination string.
158  *
159  * Arguments:
160  * char* dst (output)
161  * Destination string. The final byte of this string will always be
162  * set to NULL. If this argument is NULL, the routine is a no-op.
163  *
164  * const char* src (input)
165  * Source string. If NULL, the routine is a no-op (StrStrncat) or
166  * the destination is set to the empty string (StrStrncpy).
167  *
168  * size_t dstlen (input)
169  * Total amount of space allocated for the destination, including the
170  * terminating null byte. If this is zero, the routine is a no-op.
171  * Note that in the case of StrStrncat, this is the total amount of
172  * space IGNORING the current contents of "dst" - it is just the total
173  * space available to hold the entire resultant string.
174 -*/
175 
176 void StrStrncpy(char* dst, const char* src, size_t dstlen)
177 {
178  if (dst && (dstlen > 0)) {
179  if (src) {
180  (void) strlcpy(dst, src, dstlen);
181  /* dst[dstlen - 1] = '\0'; */
182  }
183  else {
184  dst[0] = '\0';
185  }
186  }
187 
188  return;
189 }
190 
191 void StrStrncat(char* dst, const char* src, size_t dstlen)
192 {
193  size_t length; /* Amount of space used in dst */
194  size_t remain; /* Remaining space in dst */
195 
196  if (dst) {
197  length = strlen(dst);
198  remain = dstlen - length;
199  if (remain > 1) {
200 
201  /* More space than just the trailing NULL */
202 
203  StrStrncpy(&dst[length], src, remain);
204  }
205  }
206 
207  return;
208 }
209 
210 
211 
212 /*+
213  * StrTrimR - Trim Right
214  *
215  * Description:
216  * Modifies a string by trimming white-space characters from the right of
217  * the string. It does this by modifying the string, inserting a null
218  * character after the last non white-space character.
219  *
220  * Arguments:
221  * char *text (modified)
222  * Text to modify. If this is NULL, the routine is a no-op.
223  *
224  * Returns:
225  * void
226 -*/
227 
228 void StrTrimR(char *text)
229 {
230  if (text) {
231 
232  /* Work backwards through the string */
233 
234  int textlen = strlen(text);
235  while (-- textlen >= 0) {
236  if (! isspace((int) text[textlen])) {
237  text[textlen + 1] = '\0';
238  return;
239  }
240  }
241 
242  /* Get here if the entire string is white space */
243 
244  text[0] = '\0';
245  }
246  return;
247 }
248 
249 
250 
251 /*+
252  * StrTrimL - Trim Left
253  *
254  * Description:
255  * Searches a string and returns a pointer to the first non white-space
256  * character in it.
257  *
258  * Arguments:
259  * char* text (input)
260  * Text to search.
261  *
262  * Returns:
263  * char*
264  * Pointer to first non white-space character in the string. If the
265  * string is NULL, NULL is returned. If the string is all white space,
266  * a pointer to the trailing null character is returned.
267 -*/
268 
269 char* StrTrimL(char* text)
270 {
271  if (text) {
272  while (*text && isspace((int) *text)) {
273  ++text;
274  }
275  }
276 
277  return text;
278 }
279 
280 
281 /*+
282  * StrTrim - Trim String
283  *
284  * Description:
285  * A combination of StrTrimL and StrTrimR, this routine modifies the passed
286  * string by inserting the null character after the last non-space in the
287  * string, then returning a pointer into the string to the first non
288  * white-space character.
289  *
290  * Arguments:
291  * char *text (modified)
292  * Text to be trimmed. The text may be modified.
293  *
294  * Returns:
295  * char*
296  * Pointer into text of the first non white-space character. If the
297  * input string is NULL, NULL is returned.
298 -*/
299 
300 char* StrTrim(char* text)
301 {
302  StrTrimR(text);
303  return StrTrimL(text);
304 }
305 
306 
307 /*+
308  * StrToLower - Convert to Lower Case
309  *
310  * Description:
311  * Converts the passed string to lowercase characters. As a side-effect it
312  * also returns the length of the string.
313  *
314  * Arguments:
315  * char *text (modified)
316  * String to be modified. If NULL, this routine is a no-op.
317  *
318  * Returns:
319  * size_y
320  * Length of the string.
321 -*/
322 
323 size_t StrToLower(char* string)
324 {
325  char* ptr = string;
326  if (ptr) {
327  while (*ptr) {
328  *ptr = tolower((int) *ptr);
329  ++ptr;
330  }
331  }
332 
333  return (size_t) (ptr - string);
334 }
335 
336 
337 /*+
338  * StrToUpper - Convert to Upper Case
339  *
340  * Description:
341  * Converts the passed string to uppercase characters. As a side-effect it
342  * also returns the length of the string.
343  *
344  * Arguments:
345  * char *text (modified)
346  * String to be modified. If NULL, this routine is a no-op.
347  *
348  * Returns:
349  * size_t
350  * Length of the string.
351 -*/
352 
353 size_t StrToUpper(char* string)
354 {
355  char* ptr = string;
356  if (ptr) {
357  while (*ptr) {
358  *ptr = toupper((int) *ptr);
359  ++ptr;
360  }
361  }
362 
363  return (size_t) (ptr - string);
364 }
365 
366 
367 
368 /*+
369  * StrReplaceChar - Replace Character - Null-Terminated String
370  * StrReplaceCharN - Replace Character - Length Given
371  *
372  * Description:
373  * Replaces all occurrences of a given character in a string by the given
374  * character.
375  *
376  * StrReplaceCharN is generally used where the string may contain embedded
377  * null characters in order to remove them.
378  *
379  * Arguments:
380  * char* string (modified)
381  * String in which the replacement is to take place.
382  *
383  * size_t len (input, StrReplaceCharN only)
384  * Lenght of input string.
385  *
386  * char search (input)
387  * Character to search for.
388  *
389  * char replace (input)
390  * Replacement chaaracter.
391  *
392  * Returns:
393  * size_t
394  * Number of replacements.
395 -*/
396 
397 size_t StrReplaceCharN(char* string, size_t len, char search, char replace)
398 {
399  size_t count = 0; /* Replacement count */
400  size_t i; /* Loop counter */
401 
402  if (string) {
403  for (i = 0; i < len; ++i) {
404  if (string[i] == search) {
405  string[i] = replace;
406  ++count;
407  }
408  }
409  }
410  return count;
411 }
412 
413 size_t StrReplaceChar(char* string, char search, char replace)
414 {
415  size_t count = 0; /* Replacement count */
416 
417  if (string) {
418  count = StrReplaceCharN(string, strlen(string), search, replace);
419  }
420  return count;
421 }
422 
423 
424 
425 /*+
426  * StrTrimmedLength
427  *
428  * Description:
429  * Searches the string and returns the length of the string less leading
430  * and trailing spaces. Essentially, this will be the result of a call to
431  * strlen() after the string has been passed through StrTrim().
432  *
433  * Arguments:
434  * const char* string (input)
435  * String to search.
436  *
437  * Returns:
438  * size_t
439  * Size of the string.
440 -*/
441 
442 size_t StrTrimmedLength(const char* string)
443 {
444  size_t length = 0; /* Length of trimmed string */
445  size_t in_length; /* Length of input string */
446  size_t first_char; /* Position of first non-space character */
447  size_t last_char; /* Position of last non-space character */
448 
449  if (string) {
450  in_length = strlen(string);
451 
452  /*
453  * Get offset of first non-space character. If the string does not
454  * contain any such characters, first_char will equal "length".
455  */
456 
457  first_char = 0;
458  while (first_char < in_length) {
459  if (! isspace((int) string[first_char])) {
460  break;
461  }
462  ++first_char;
463  }
464 
465  if (first_char < in_length) {
466 
467  /*
468  * Must be a printable character, so find the offset of the last
469  * such character.
470  */
471 
472  last_char = in_length - 1;
473  while (isspace((int) string[last_char])) {
474  --last_char;
475  }
476 
477  /* ... and work out the length */
478 
479  length = last_char - first_char + 1;
480  assert(length > 0);
481  }
482 
483  /* No "else" - length is set to zero on enty */
484  }
485 
486  return length;
487 }
void * MemCalloc(size_t nmemb, size_t size)
Definition: memory.c:68
char * StrTrim(char *text)
Definition: string_util.c:300
int MsgLog(int status,...)
Definition: message.c:335
void StrWhitespace(char *line)
Definition: string_util.c:94
size_t StrToLower(char *string)
Definition: string_util.c:323
void StrStrncat(char *dst, const char *src, size_t dstlen)
Definition: string_util.c:191
void StrUncomment(char *line)
Definition: string_util.c:65
#define KSM_STMTALLOC
Definition: ksmdef.h:77
size_t StrTrimmedLength(const char *string)
Definition: string_util.c:442
char * StrStrdup(const char *string)
Definition: string_util.c:124
void StrStrncpy(char *dst, const char *src, size_t dstlen)
Definition: string_util.c:176
void StrTrimR(char *text)
Definition: string_util.c:228
#define COMMENT_CHAR
Definition: string_util.h:44
size_t StrToUpper(char *string)
Definition: string_util.c:353
size_t StrReplaceCharN(char *string, size_t len, char search, char replace)
Definition: string_util.c:397
size_t StrReplaceChar(char *string, char search, char replace)
Definition: string_util.c:413
char * StrTrimL(char *text)
Definition: string_util.c:269