1 /*
2 * Copyright (C) 2012-2015 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20
21 #include <glib/gprintf.h>
22 #include <locale.h>
23 #ifdef WITH_XLOCALE_H
24 # include <xlocale.h>
25 #endif
26
27 #include "virstring.h"
28 #include "virthread.h"
29 #include "viralloc.h"
30 #include "virbuffer.h"
31 #include "virerror.h"
32 #include "virlog.h"
33
34 #define VIR_FROM_THIS VIR_FROM_NONE
35
36 VIR_LOG_INIT("util.string");
37
38 /* Like strtol, but produce an "int" result, and check more carefully.
39 Return 0 upon success; return -1 to indicate failure.
40 When END_PTR is NULL, the byte after the final valid digit must be NUL.
41 Otherwise, it's like strtol and lets the caller check any suffix for
42 validity. This function is careful to return -1 when the string S
43 represents a number that is not representable as an "int". */
44 int
virStrToLong_i(char const * s,char ** end_ptr,int base,int * result)45 virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
46 {
47 long int val;
48 char *p;
49 int err;
50
51 errno = 0;
52 val = strtol(s, &p, base); /* exempt from syntax-check */
53 err = (errno || (!end_ptr && *p) || p == s || (int) val != val);
54 if (end_ptr)
55 *end_ptr = p;
56 if (err)
57 return -1;
58 *result = val;
59 return 0;
60 }
61
62 /* Just like virStrToLong_i, above, but produce an "unsigned int"
63 * value. This version allows twos-complement wraparound of negative
64 * numbers. */
65 int
virStrToLong_ui(char const * s,char ** end_ptr,int base,unsigned int * result)66 virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
67 {
68 unsigned long int val;
69 char *p;
70 bool err = false;
71
72 errno = 0;
73 val = strtoul(s, &p, base); /* exempt from syntax-check */
74
75 /* This one's tricky. We _want_ to allow "-1" as shorthand for
76 * UINT_MAX regardless of whether long is 32-bit or 64-bit. But
77 * strtoul treats "-1" as ULONG_MAX, and going from ulong back
78 * to uint differs depending on the size of long. */
79 if (sizeof(long) > sizeof(int) && memchr(s, '-', p - s)) {
80 if (-val > UINT_MAX)
81 err = true;
82 else
83 val &= 0xffffffff;
84 }
85
86 err |= (errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
87 if (end_ptr)
88 *end_ptr = p;
89 if (err)
90 return -1;
91 *result = val;
92 return 0;
93 }
94
95 /* Just like virStrToLong_i, above, but produce an "unsigned int"
96 * value. This version rejects any negative signs. */
97 int
virStrToLong_uip(char const * s,char ** end_ptr,int base,unsigned int * result)98 virStrToLong_uip(char const *s, char **end_ptr, int base, unsigned int *result)
99 {
100 unsigned long int val;
101 char *p;
102 bool err = false;
103
104 errno = 0;
105 val = strtoul(s, &p, base); /* exempt from syntax-check */
106 err = (memchr(s, '-', p - s) ||
107 errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
108 if (end_ptr)
109 *end_ptr = p;
110 if (err)
111 return -1;
112 *result = val;
113 return 0;
114 }
115
116 /* Just like virStrToLong_i, above, but produce a "long" value. */
117 int
virStrToLong_l(char const * s,char ** end_ptr,int base,long * result)118 virStrToLong_l(char const *s, char **end_ptr, int base, long *result)
119 {
120 long int val;
121 char *p;
122 int err;
123
124 errno = 0;
125 val = strtol(s, &p, base); /* exempt from syntax-check */
126 err = (errno || (!end_ptr && *p) || p == s);
127 if (end_ptr)
128 *end_ptr = p;
129 if (err)
130 return -1;
131 *result = val;
132 return 0;
133 }
134
135 /* Just like virStrToLong_i, above, but produce an "unsigned long"
136 * value. This version allows twos-complement wraparound of negative
137 * numbers. */
138 int
virStrToLong_ul(char const * s,char ** end_ptr,int base,unsigned long * result)139 virStrToLong_ul(char const *s, char **end_ptr, int base, unsigned long *result)
140 {
141 unsigned long int val;
142 char *p;
143 int err;
144
145 errno = 0;
146 val = strtoul(s, &p, base); /* exempt from syntax-check */
147 err = (errno || (!end_ptr && *p) || p == s);
148 if (end_ptr)
149 *end_ptr = p;
150 if (err)
151 return -1;
152 *result = val;
153 return 0;
154 }
155
156 /* Just like virStrToLong_i, above, but produce an "unsigned long"
157 * value. This version rejects any negative signs. */
158 int
virStrToLong_ulp(char const * s,char ** end_ptr,int base,unsigned long * result)159 virStrToLong_ulp(char const *s, char **end_ptr, int base,
160 unsigned long *result)
161 {
162 unsigned long int val;
163 char *p;
164 int err;
165
166 errno = 0;
167 val = strtoul(s, &p, base); /* exempt from syntax-check */
168 err = (memchr(s, '-', p - s) ||
169 errno || (!end_ptr && *p) || p == s);
170 if (end_ptr)
171 *end_ptr = p;
172 if (err)
173 return -1;
174 *result = val;
175 return 0;
176 }
177
178 /* Just like virStrToLong_i, above, but produce a "long long" value. */
179 int
virStrToLong_ll(char const * s,char ** end_ptr,int base,long long * result)180 virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)
181 {
182 long long val;
183 char *p;
184 int err;
185
186 errno = 0;
187 val = strtoll(s, &p, base); /* exempt from syntax-check */
188 err = (errno || (!end_ptr && *p) || p == s);
189 if (end_ptr)
190 *end_ptr = p;
191 if (err)
192 return -1;
193 *result = val;
194 return 0;
195 }
196
197 /* Just like virStrToLong_i, above, but produce an "unsigned long
198 * long" value. This version allows twos-complement wraparound of
199 * negative numbers. */
200 int
virStrToLong_ull(char const * s,char ** end_ptr,int base,unsigned long long * result)201 virStrToLong_ull(char const *s, char **end_ptr, int base,
202 unsigned long long *result)
203 {
204 unsigned long long val;
205 char *p;
206 int err;
207
208 errno = 0;
209 val = strtoull(s, &p, base); /* exempt from syntax-check */
210 err = (errno || (!end_ptr && *p) || p == s);
211 if (end_ptr)
212 *end_ptr = p;
213 if (err)
214 return -1;
215 *result = val;
216 return 0;
217 }
218
219 /* Just like virStrToLong_i, above, but produce an "unsigned long
220 * long" value. This version rejects any negative signs. */
221 int
virStrToLong_ullp(char const * s,char ** end_ptr,int base,unsigned long long * result)222 virStrToLong_ullp(char const *s, char **end_ptr, int base,
223 unsigned long long *result)
224 {
225 unsigned long long val;
226 char *p;
227 int err;
228
229 errno = 0;
230 val = strtoull(s, &p, base); /* exempt from syntax-check */
231 err = (memchr(s, '-', p - s) ||
232 errno || (!end_ptr && *p) || p == s);
233 if (end_ptr)
234 *end_ptr = p;
235 if (err)
236 return -1;
237 *result = val;
238 return 0;
239 }
240
241 /* In case thread-safe locales are available */
242 #if WITH_NEWLOCALE
243
244 typedef locale_t virLocale;
245 static virLocale virLocaleRaw;
246
247 static int
virLocaleOnceInit(void)248 virLocaleOnceInit(void)
249 {
250 virLocaleRaw = newlocale(LC_ALL_MASK, "C", (locale_t)0);
251 if (!virLocaleRaw)
252 return -1;
253 return 0;
254 }
255
256 VIR_ONCE_GLOBAL_INIT(virLocale);
257
258 /**
259 * virLocaleSetRaw:
260 *
261 * @oldlocale: set to old locale pointer
262 *
263 * Sets the locale to 'C' to allow operating on non-localized objects.
264 * Returns 0 on success -1 on error.
265 */
266 static int
virLocaleSetRaw(virLocale * oldlocale)267 virLocaleSetRaw(virLocale *oldlocale)
268 {
269 if (virLocaleInitialize() < 0)
270 return -1;
271 *oldlocale = uselocale(virLocaleRaw);
272 return 0;
273 }
274
275 static void
virLocaleRevert(virLocale * oldlocale)276 virLocaleRevert(virLocale *oldlocale)
277 {
278 uselocale(*oldlocale);
279 }
280
281 static void
virLocaleFixupRadix(char ** strp G_GNUC_UNUSED)282 virLocaleFixupRadix(char **strp G_GNUC_UNUSED)
283 {
284 }
285
286 #else /* !WITH_NEWLOCALE */
287
288 typedef int virLocale;
289
290 static int
virLocaleSetRaw(virLocale * oldlocale G_GNUC_UNUSED)291 virLocaleSetRaw(virLocale *oldlocale G_GNUC_UNUSED)
292 {
293 return 0;
294 }
295
296 static void
virLocaleRevert(virLocale * oldlocale G_GNUC_UNUSED)297 virLocaleRevert(virLocale *oldlocale G_GNUC_UNUSED)
298 {
299 }
300
301 static void
virLocaleFixupRadix(char ** strp)302 virLocaleFixupRadix(char **strp)
303 {
304 char *radix, *tmp;
305 struct lconv *lc;
306
307 lc = localeconv();
308 radix = lc->decimal_point;
309 tmp = strstr(*strp, radix);
310 if (tmp) {
311 *tmp = '.';
312 if (strlen(radix) > 1)
313 memmove(tmp + 1, tmp + strlen(radix), strlen(*strp) - (tmp - *strp));
314 }
315 }
316
317 #endif /* !WITH_NEWLOCALE */
318
319
320 /**
321 * virStrToDouble
322 *
323 * converts string with C locale (thread-safe) to double.
324 *
325 * Returns -1 on error or returns 0 on success.
326 */
327 int
virStrToDouble(char const * s,char ** end_ptr,double * result)328 virStrToDouble(char const *s,
329 char **end_ptr,
330 double *result)
331 {
332 virLocale oldlocale;
333 double val;
334 char *p;
335 int err;
336
337 errno = 0;
338 if (virLocaleSetRaw(&oldlocale) < 0)
339 return -1;
340 val = strtod(s, &p); /* exempt from syntax-check */
341 virLocaleRevert(&oldlocale);
342
343 err = (errno || (!end_ptr && *p) || p == s);
344 if (end_ptr)
345 *end_ptr = p;
346 if (err)
347 return -1;
348 *result = val;
349 return 0;
350 }
351
352 /**
353 * virDoubleToStr
354 *
355 * converts double to string with C locale (thread-safe).
356 *
357 * Returns: 0 on success, -1 otherwise.
358 */
359 int
virDoubleToStr(char ** strp,double number)360 virDoubleToStr(char **strp, double number)
361 {
362 virLocale oldlocale;
363
364 if (virLocaleSetRaw(&oldlocale) < 0)
365 return -1;
366
367 *strp = g_strdup_printf("%lf", number);
368
369 virLocaleRevert(&oldlocale);
370 virLocaleFixupRadix(strp);
371
372 return 0;
373 }
374
375
376 /**
377 * virStrcpy:
378 *
379 * @dest: destination buffer
380 * @src: source buffer
381 * @destbytes: number of bytes the destination can accommodate
382 *
383 * Copies @src to @dest. @dest is guaranteed to be 'nul' terminated if
384 * destbytes is 1 or more.
385 *
386 * Returns: 0 on success, -1 if @src doesn't fit into @dest and was truncated.
387 */
388 int
virStrcpy(char * dest,const char * src,size_t destbytes)389 virStrcpy(char *dest, const char *src, size_t destbytes)
390 {
391 if (g_strlcpy(dest, src, destbytes) >= destbytes)
392 return -1;
393
394 return 0;
395 }
396
397 /**
398 * virSkipSpaces:
399 * @str: pointer to the char pointer used
400 *
401 * Skip potential blanks, this includes space tabs, line feed,
402 * carriage returns.
403 */
404 void
virSkipSpaces(const char ** str)405 virSkipSpaces(const char **str)
406 {
407 const char *cur = *str;
408
409 while (g_ascii_isspace(*cur))
410 cur++;
411 *str = cur;
412 }
413
414 /**
415 * virSkipSpacesAndBackslash:
416 * @str: pointer to the char pointer used
417 *
418 * Like virSkipSpaces, but also skip backslashes erroneously emitted
419 * by xend
420 */
421 void
virSkipSpacesAndBackslash(const char ** str)422 virSkipSpacesAndBackslash(const char **str)
423 {
424 const char *cur = *str;
425
426 while (g_ascii_isspace(*cur) || *cur == '\\')
427 cur++;
428 *str = cur;
429 }
430
431
432 /**
433 * virSkipToDigit:
434 * @str: pointer to the char pointer used
435 *
436 * Skip over any character that is not 0-9
437 */
438 void
virSkipToDigit(const char ** str)439 virSkipToDigit(const char **str)
440 {
441 const char *cur = *str;
442
443 while (*cur && !g_ascii_isdigit(*cur))
444 cur++;
445 *str = cur;
446 }
447
448
449 /**
450 * virTrimSpaces:
451 * @str: string to modify to remove all trailing spaces
452 * @endp: track the end of the string
453 *
454 * If @endp is NULL on entry, then all spaces prior to the trailing
455 * NUL in @str are removed, by writing NUL into the appropriate
456 * location. If @endp is non-NULL but points to a NULL pointer,
457 * then all spaces prior to the trailing NUL in @str are removed,
458 * NUL is written to the new string end, and endp is set to the
459 * location of the (new) string end. If @endp is non-NULL and
460 * points to a non-NULL pointer, then that pointer is used as
461 * the end of the string, endp is set to the (new) location, but
462 * no NUL pointer is written into the string.
463 */
464 void
virTrimSpaces(char * str,char ** endp)465 virTrimSpaces(char *str, char **endp)
466 {
467 char *end;
468
469 if (!endp || !*endp)
470 end = str + strlen(str);
471 else
472 end = *endp;
473 while (end > str && g_ascii_isspace(end[-1]))
474 end--;
475 if (endp) {
476 if (!*endp)
477 *end = '\0';
478 *endp = end;
479 } else {
480 *end = '\0';
481 }
482 }
483
484 /**
485 * virSkipSpacesBackwards:
486 * @str: start of string
487 * @endp: on entry, *endp must be NULL or a location within @str, on exit,
488 * will be adjusted to skip trailing spaces, or to NULL if @str had nothing
489 * but spaces.
490 */
491 void
virSkipSpacesBackwards(const char * str,char ** endp)492 virSkipSpacesBackwards(const char *str, char **endp)
493 {
494 /* Casting away const is safe, since virTrimSpaces does not
495 * modify string with this particular usage. */
496 char *s = (char*) str;
497
498 if (!*endp)
499 *endp = s + strlen(s);
500 virTrimSpaces(s, endp);
501 if (s == *endp)
502 *endp = NULL;
503 }
504
505 /**
506 * virStringIsEmpty:
507 * @str: string to check
508 *
509 * Returns true if string is empty (may contain only whitespace) or NULL.
510 */
511 bool
virStringIsEmpty(const char * str)512 virStringIsEmpty(const char *str)
513 {
514 if (!str)
515 return true;
516
517 virSkipSpaces(&str);
518 return str[0] == '\0';
519 }
520
521
522 /**
523 * virStringSortCompare:
524 *
525 * A comparator function for sorting strings in
526 * normal order with qsort().
527 */
virStringSortCompare(const void * a,const void * b)528 int virStringSortCompare(const void *a, const void *b)
529 {
530 const char **sa = (const char**)a;
531 const char **sb = (const char**)b;
532
533 return strcmp(*sa, *sb);
534 }
535
536 /**
537 * virStringSortRevCompare:
538 *
539 * A comparator function for sorting strings in
540 * reverse order with qsort().
541 */
virStringSortRevCompare(const void * a,const void * b)542 int virStringSortRevCompare(const void *a, const void *b)
543 {
544 const char **sa = (const char**)a;
545 const char **sb = (const char**)b;
546
547 return strcmp(*sb, *sa);
548 }
549
550 /**
551 * virStringSearch:
552 * @str: string to search
553 * @regexp: POSIX Extended regular expression pattern used for matching
554 * @max_matches: maximum number of substrings to return
555 * @matches: pointer to an array to be filled with NULL terminated list of matches
556 *
557 * Performs a POSIX extended regex search against a string and return all matching substrings.
558 * The @matches value should be freed with g_strfreev() when no longer
559 * required.
560 *
561 * @code
562 * char *source = "6853a496-1c10-472e-867a-8244937bd6f0
563 * 773ab075-4cd7-4fc2-8b6e-21c84e9cb391
564 * bbb3c75c-d60f-43b0-b802-fd56b84a4222
565 * 60c04aa1-0375-4654-8d9f-e149d9885273
566 * 4548d465-9891-4c34-a184-3b1c34a26aa8";
567 * char **matches = NULL;
568 * virStringSearch(source,
569 * "([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
570 * 3,
571 * &matches);
572 *
573 * // matches[0] == "6853a496-1c10-472e-867a-8244937bd6f0";
574 * // matches[1] == "773ab075-4cd7-4fc2-8b6e-21c84e9cb391";
575 * // matches[2] == "bbb3c75c-d60f-43b0-b802-fd56b84a4222"
576 * // matches[3] == NULL;
577 *
578 * g_strfreev(matches);
579 * @endcode
580 *
581 * Returns: -1 on error, or number of matches
582 */
583 ssize_t
virStringSearch(const char * str,const char * regexp,size_t max_matches,char *** matches)584 virStringSearch(const char *str,
585 const char *regexp,
586 size_t max_matches,
587 char ***matches)
588 {
589 g_autoptr(GRegex) regex = NULL;
590 g_autoptr(GError) err = NULL;
591 size_t nmatches = 0;
592 ssize_t ret = -1;
593
594 *matches = NULL;
595
596 VIR_DEBUG("search '%s' for '%s'", str, regexp);
597
598 regex = g_regex_new(regexp, 0, 0, &err);
599 if (!regex) {
600 virReportError(VIR_ERR_INTERNAL_ERROR,
601 _("Failed to compile regex %s"), err->message);
602 return -1;
603 }
604
605 if (g_regex_get_capture_count(regex) != 1) {
606 virReportError(VIR_ERR_INTERNAL_ERROR,
607 _("Regular expression '%s' must have exactly 1 match group, not %d"),
608 regexp, g_regex_get_capture_count(regex));
609 goto cleanup;
610 }
611
612 /* '*matches' must always be NULL terminated in every iteration
613 * of the loop, so start by allocating 1 element
614 */
615 VIR_EXPAND_N(*matches, nmatches, 1);
616
617 while ((nmatches - 1) < max_matches) {
618 g_autoptr(GMatchInfo) info = NULL;
619 char *match;
620 int endpos;
621
622 if (!g_regex_match(regex, str, 0, &info))
623 break;
624
625 VIR_EXPAND_N(*matches, nmatches, 1);
626
627 match = g_match_info_fetch(info, 1);
628
629 VIR_DEBUG("Got '%s'", match);
630
631 (*matches)[nmatches-2] = match;
632
633 g_match_info_fetch_pos(info, 1, NULL, &endpos);
634 str += endpos;
635 }
636
637 ret = nmatches - 1; /* don't count the trailing null */
638
639 cleanup:
640 if (ret < 0) {
641 g_strfreev(*matches);
642 *matches = NULL;
643 }
644 return ret;
645 }
646
647 /**
648 * virStringMatch:
649 * @str: string to match
650 * @regexp: POSIX Extended regular expression pattern used for matching
651 *
652 * Performs a POSIX extended regex match against a string.
653 * Returns true on match, false on error or no match.
654 */
655 bool
virStringMatch(const char * str,const char * regexp)656 virStringMatch(const char *str,
657 const char *regexp)
658 {
659 g_autoptr(GRegex) regex = NULL;
660 g_autoptr(GError) err = NULL;
661
662 VIR_DEBUG("match '%s' for '%s'", str, regexp);
663
664 regex = g_regex_new(regexp, 0, 0, &err);
665 if (!regex) {
666 VIR_WARN("Failed to compile regex %s", err->message);
667 return false;
668 }
669
670 return g_regex_match(regex, str, 0, NULL);
671 }
672
673 /**
674 * virStringReplace:
675 * @haystack: the source string to process
676 * @oldneedle: the substring to locate
677 * @newneedle: the substring to insert
678 *
679 * Search @haystack and replace all occurrences of @oldneedle with @newneedle.
680 *
681 * Returns: a new string with all the replacements, or NULL on error
682 */
683 char *
virStringReplace(const char * haystack,const char * oldneedle,const char * newneedle)684 virStringReplace(const char *haystack,
685 const char *oldneedle,
686 const char *newneedle)
687 {
688 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
689 const char *tmp1, *tmp2;
690 size_t oldneedlelen = strlen(oldneedle);
691 size_t newneedlelen = strlen(newneedle);
692
693 tmp1 = haystack;
694 tmp2 = NULL;
695
696 while (tmp1) {
697 tmp2 = strstr(tmp1, oldneedle);
698
699 if (tmp2) {
700 virBufferAdd(&buf, tmp1, (tmp2 - tmp1));
701 virBufferAdd(&buf, newneedle, newneedlelen);
702 tmp2 += oldneedlelen;
703 } else {
704 virBufferAdd(&buf, tmp1, -1);
705 }
706
707 tmp1 = tmp2;
708 }
709
710 return virBufferContentAndReset(&buf);
711 }
712
713 bool
virStringHasSuffix(const char * str,const char * suffix)714 virStringHasSuffix(const char *str,
715 const char *suffix)
716 {
717 int len = strlen(str);
718 int suffixlen = strlen(suffix);
719
720 if (len < suffixlen)
721 return false;
722
723 return STREQ(str + len - suffixlen, suffix);
724 }
725
726 bool
virStringHasCaseSuffix(const char * str,const char * suffix)727 virStringHasCaseSuffix(const char *str,
728 const char *suffix)
729 {
730 int len = strlen(str);
731 int suffixlen = strlen(suffix);
732
733 if (len < suffixlen)
734 return false;
735
736 return STRCASEEQ(str + len - suffixlen, suffix);
737 }
738
739 bool
virStringStripSuffix(char * str,const char * suffix)740 virStringStripSuffix(char *str,
741 const char *suffix)
742 {
743 int len = strlen(str);
744 int suffixlen = strlen(suffix);
745
746 if (len < suffixlen)
747 return false;
748
749 if (STRNEQ(str + len - suffixlen, suffix))
750 return false;
751
752 str[len - suffixlen] = '\0';
753
754 return true;
755 }
756
757 bool
virStringMatchesNameSuffix(const char * file,const char * name,const char * suffix)758 virStringMatchesNameSuffix(const char *file,
759 const char *name,
760 const char *suffix)
761 {
762 int filelen = strlen(file);
763 int namelen = strlen(name);
764 int suffixlen = strlen(suffix);
765
766 if (filelen == (namelen + suffixlen) &&
767 STREQLEN(file, name, namelen) &&
768 STREQ(file + namelen, suffix))
769 return true;
770 else
771 return false;
772 }
773
774 /**
775 * virStringStripIPv6Brackets:
776 * @str: the string to strip
777 *
778 * Modify the string in-place to remove the leading and closing brackets
779 * from an IPv6 address.
780 */
781 void
virStringStripIPv6Brackets(char * str)782 virStringStripIPv6Brackets(char *str)
783 {
784 size_t len;
785
786 if (!str)
787 return;
788
789 len = strlen(str);
790 if (str[0] == '[' && str[len - 1] == ']' && strchr(str, ':')) {
791 memmove(&str[0], &str[1], len - 2);
792 str[len - 2] = '\0';
793 }
794 }
795
796
797 /**
798 * virStringHasChars:
799 * @str: string to look for chars in
800 * @chars: chars to find in string @str
801 *
802 * Returns true if @str contains any of the chars in @chars.
803 */
804 bool
virStringHasChars(const char * str,const char * chars)805 virStringHasChars(const char *str,
806 const char *chars)
807 {
808 if (!str)
809 return false;
810
811 return str[strcspn(str, chars)] != '\0';
812 }
813
814
815 static const char control_chars[] =
816 "\x01\x02\x03\x04\x05\x06\x07"
817 "\x08" /* \t \n */ "\x0B\x0C" /* \r */ "\x0E\x0F"
818 "\x10\x11\x12\x13\x14\x15\x16\x17"
819 "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
820
821 bool
virStringHasControlChars(const char * str)822 virStringHasControlChars(const char *str)
823 {
824 return virStringHasChars(str, control_chars);
825 }
826
827
828 /**
829 * virStringStripControlChars:
830 * @str: the string to strip
831 *
832 * Modify the string in-place to remove the control characters
833 * in the interval: [0x01, 0x20)
834 */
835 void
virStringStripControlChars(char * str)836 virStringStripControlChars(char *str)
837 {
838 size_t len, i, j;
839
840 if (!str)
841 return;
842
843 len = strlen(str);
844 for (i = 0, j = 0; i < len; i++) {
845 if (strchr(control_chars, str[i]))
846 continue;
847
848 str[j++] = str[i];
849 }
850 str[j] = '\0';
851 }
852
853 /**
854 * virStringFilterChars:
855 * @str: the string to strip
856 * @valid: the valid characters for the string
857 *
858 * Modify the string in-place to remove the characters that aren't
859 * in the list of valid ones.
860 */
861 void
virStringFilterChars(char * str,const char * valid)862 virStringFilterChars(char *str, const char *valid)
863 {
864 size_t len, i, j;
865
866 if (!str)
867 return;
868
869 len = strlen(str);
870 for (i = 0, j = 0; i < len; i++) {
871 if (strchr(valid, str[i]))
872 str[j++] = str[i];
873 }
874 str[j] = '\0';
875 }
876
877 /**
878 * virStringToUpper:
879 * @src string to capitalize
880 * @dst: where to store the new capitalized string
881 *
882 * Capitalize the string with replacement of all '-' characters for '_'
883 * characters. Caller frees the result.
884 *
885 * Returns 0 if src is NULL, 1 if capitalization was successful, -1 on failure.
886 */
887 int
virStringToUpper(char ** dst,const char * src)888 virStringToUpper(char **dst, const char *src)
889 {
890 char *cap = NULL;
891 size_t i;
892
893 if (!src)
894 return 0;
895
896 cap = g_new0(char, strlen(src) + 1);
897
898 for (i = 0; src[i]; i++) {
899 cap[i] = g_ascii_toupper(src[i]);
900 if (cap[i] == '-')
901 cap[i] = '_';
902 }
903
904 *dst = cap;
905 return 1;
906 }
907
908
909 /**
910 * virStringIsPrintable:
911 *
912 * Returns true @str contains only printable characters.
913 */
914 bool
virStringIsPrintable(const char * str)915 virStringIsPrintable(const char *str)
916 {
917 size_t i;
918
919 for (i = 0; str[i]; i++)
920 if (!g_ascii_isprint(str[i]))
921 return false;
922
923 return true;
924 }
925
926
927 /**
928 * virBufferIsPrintable:
929 *
930 * Returns true if @buf of @buflen contains only printable characters
931 */
932 bool
virStringBufferIsPrintable(const uint8_t * buf,size_t buflen)933 virStringBufferIsPrintable(const uint8_t *buf,
934 size_t buflen)
935 {
936 size_t i;
937
938 for (i = 0; i < buflen; i++)
939 if (!g_ascii_isprint(buf[i]))
940 return false;
941
942 return true;
943 }
944
945
946 /**
947 * virStringTrimOptionalNewline:
948 * @str: the string to modify in-place
949 *
950 * Modify @str to remove a single '\n' character
951 * from its end, if one exists.
952 */
virStringTrimOptionalNewline(char * str)953 void virStringTrimOptionalNewline(char *str)
954 {
955 size_t len = strlen(str);
956
957 if (!len)
958 return;
959
960 if (str[len - 1] == '\n')
961 str[len - 1] = '\0';
962 }
963
964
965 /**
966 * virStringParsePort:
967 * @str: port number to parse
968 * @port: pointer to parse port into
969 *
970 * Parses a string representation of a network port and validates it. Returns
971 * 0 on success and -1 on error.
972 */
973 int
virStringParsePort(const char * str,unsigned int * port)974 virStringParsePort(const char *str,
975 unsigned int *port)
976 {
977 unsigned int p = 0;
978
979 *port = 0;
980
981 if (!str)
982 return 0;
983
984 if (virStrToLong_uip(str, NULL, 10, &p) < 0) {
985 virReportError(VIR_ERR_INVALID_ARG,
986 _("failed to parse port number '%s'"), str);
987 return -1;
988 }
989
990 if (p > UINT16_MAX) {
991 virReportError(VIR_ERR_INVALID_ARG,
992 _("port '%s' out of range"), str);
993 return -1;
994 }
995
996 *port = p;
997
998 return 0;
999 }
1000
1001
1002 /**
1003 * virStringParseYesNo:
1004 * @str: "yes|no" to parse, must not be NULL.
1005 * @result: pointer to the boolean result of @str conversion
1006 *
1007 * Parses a "yes|no" string and converts it into a boolean.
1008 *
1009 * Returns 0 on success and -1 on error.
1010 */
virStringParseYesNo(const char * str,bool * result)1011 int virStringParseYesNo(const char *str, bool *result)
1012 {
1013 if (STREQ(str, "yes"))
1014 *result = true;
1015 else if (STREQ(str, "no"))
1016 *result = false;
1017 else
1018 return -1;
1019
1020 return 0;
1021 }
1022