root/lib/common/strings.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. crm_itoa_stack
  2. scan_ll
  3. crm_parse_ll
  4. crm_parse_int
  5. pcmk__scan_double
  6. pcmk__guint_from_hash
  7. crm_get_msec
  8. crm_is_true
  9. crm_str_to_boolean
  10. crm_strip_trailing_newline
  11. pcmk__starts_with
  12. ends_with
  13. pcmk__ends_with
  14. pcmk__ends_with_ext
  15. g_str_hash_traditional
  16. crm_strcase_equal
  17. crm_strcase_hash
  18. copy_str_table_entry
  19. crm_str_table_dup
  20. pcmk__add_separated_word
  21. pcmk__compress
  22. crm_strdup_printf
  23. pcmk__parse_ll_range
  24. pcmk__str_in_list
  25. str_any_of
  26. pcmk__strcase_any_of
  27. pcmk__str_any_of
  28. pcmk__char_in_any_str
  29. pcmk_numeric_strcasecmp
  30. pcmk__strcmp
  31. safe_str_neq
  32. crm_str_eq

   1 /*
   2  * Copyright 2004-2020 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #ifndef _GNU_SOURCE
  13 #  define _GNU_SOURCE
  14 #endif
  15 
  16 #include <regex.h>
  17 #include <stdio.h>
  18 #include <string.h>
  19 #include <stdlib.h>
  20 #include <ctype.h>
  21 #include <float.h>  // DBL_MIN
  22 #include <limits.h>
  23 #include <math.h>   // fabs()
  24 #include <bzlib.h>
  25 #include <sys/types.h>
  26 
  27 char *
  28 crm_itoa_stack(int an_int, char *buffer, size_t len)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30     if (buffer != NULL) {
  31         snprintf(buffer, len, "%d", an_int);
  32     }
  33 
  34     return buffer;
  35 }
  36 
  37 /*!
  38  * \internal
  39  * \brief Scan a long long integer from a string
  40  *
  41  * \param[in]  text      String to scan
  42  * \param[out] result    If not NULL, where to store scanned value
  43  * \param[out] end_text  If not NULL, where to store pointer to just after value
  44  *
  45  * \return Standard Pacemaker return code (\c pcmk_rc_ok on success,
  46  *         \c EINVAL on failed string conversion due to invalid input,
  47  *         or \c EOVERFLOW on arithmetic overflow)
  48  * \note Sets \c errno on error
  49  */
  50 static int
  51 scan_ll(const char *text, long long *result, char **end_text)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53     long long local_result = PCMK__PARSE_INT_DEFAULT;
  54     char *local_end_text = NULL;
  55     int rc = pcmk_rc_ok;
  56 
  57     errno = 0;
  58     if (text != NULL) {
  59 #ifdef ANSI_ONLY
  60         local_result = (long long) strtol(text, &local_end_text, 10);
  61 #else
  62         local_result = strtoll(text, &local_end_text, 10);
  63 #endif
  64         if (errno == ERANGE) {
  65             rc = EOVERFLOW;
  66             crm_warn("Integer parsed from %s was clipped to %lld",
  67                      text, local_result);
  68 
  69         } else if (errno != 0) {
  70             rc = errno;
  71             local_result = PCMK__PARSE_INT_DEFAULT;
  72             crm_warn("Could not parse integer from %s (using %d instead): %s",
  73                     text, PCMK__PARSE_INT_DEFAULT, pcmk_rc_str(rc));
  74 
  75         } else if (local_end_text == text) {
  76             rc = EINVAL;
  77             local_result = PCMK__PARSE_INT_DEFAULT;
  78             crm_warn("Could not parse integer from %s (using %d instead): "
  79                     "No digits found", text, PCMK__PARSE_INT_DEFAULT);
  80         }
  81 
  82         if ((end_text == NULL) && !pcmk__str_empty(local_end_text)) {
  83             crm_warn("Characters left over after parsing '%s': '%s'",
  84                      text, local_end_text);
  85         }
  86         errno = rc;
  87     }
  88     if (end_text != NULL) {
  89         *end_text = local_end_text;
  90     }
  91     if (result != NULL) {
  92         *result = local_result;
  93     }
  94     return rc;
  95 }
  96 
  97 /*!
  98  * \brief Parse a long long integer value from a string
  99  *
 100  * \param[in] text          The string to parse
 101  * \param[in] default_text  Default string to parse if text is NULL
 102  *
 103  * \return Parsed value on success, PCMK__PARSE_INT_DEFAULT (and set
 104  *         errno) on error
 105  */
 106 long long
 107 crm_parse_ll(const char *text, const char *default_text)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109     long long result;
 110 
 111     if (text == NULL) {
 112         text = default_text;
 113         if (text == NULL) {
 114             crm_err("No default conversion value supplied");
 115             errno = EINVAL;
 116             return PCMK__PARSE_INT_DEFAULT;
 117         }
 118     }
 119     scan_ll(text, &result, NULL);
 120     return result;
 121 }
 122 
 123 /*!
 124  * \brief Parse an integer value from a string
 125  *
 126  * \param[in] text          The string to parse
 127  * \param[in] default_text  Default string to parse if text is NULL
 128  *
 129  * \return Parsed value on success, INT_MIN or INT_MAX (and set errno to
 130  *         ERANGE) if parsed value is out of integer range, otherwise
 131  *         PCMK__PARSE_INT_DEFAULT (and set errno)
 132  */
 133 int
 134 crm_parse_int(const char *text, const char *default_text)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136     long long result = crm_parse_ll(text, default_text);
 137 
 138     if (result < INT_MIN) {
 139         // If errno is ERANGE, crm_parse_ll() has already logged a message
 140         if (errno != ERANGE) {
 141             crm_err("Conversion of %s was clipped: %lld", text, result);
 142             errno = ERANGE;
 143         }
 144         return INT_MIN;
 145 
 146     } else if (result > INT_MAX) {
 147         // If errno is ERANGE, crm_parse_ll() has already logged a message
 148         if (errno != ERANGE) {
 149             crm_err("Conversion of %s was clipped: %lld", text, result);
 150             errno = ERANGE;
 151         }
 152         return INT_MAX;
 153     }
 154 
 155     return (int) result;
 156 }
 157 
 158 /*!
 159  * \internal
 160  * \brief Scan a double-precision floating-point value from a string
 161  *
 162  * \param[in]      text         The string to parse
 163  * \param[out]     result       Parsed value on success, or
 164  *                              \c PCMK__PARSE_DBL_DEFAULT on error
 165  * \param[in]      default_text Default string to parse if \p text is
 166  *                              \c NULL
 167  * \param[out]     end_text     If not \c NULL, where to store a pointer
 168  *                              to the position immediately after the
 169  *                              value
 170  *
 171  * \return Standard Pacemaker return code (\c pcmk_rc_ok on success,
 172  *         \c EINVAL on failed string conversion due to invalid input,
 173  *         \c EOVERFLOW on arithmetic overflow, \c pcmk_rc_underflow
 174  *         on arithmetic underflow, or \c errno from \c strtod() on
 175  *         other parse errors)
 176  */
 177 int
 178 pcmk__scan_double(const char *text, double *result, const char *default_text,
     /* [previous][next][first][last][top][bottom][index][help] */
 179                   char **end_text)
 180 {
 181     int rc = pcmk_rc_ok;
 182     char *local_end_text = NULL;
 183 
 184     CRM_ASSERT(result != NULL);
 185     *result = PCMK__PARSE_DBL_DEFAULT;
 186 
 187     text = (text != NULL) ? text : default_text;
 188 
 189     if (text == NULL) {
 190         rc = EINVAL;
 191         crm_debug("No text and no default conversion value supplied");
 192 
 193     } else {
 194         errno = 0;
 195         *result = strtod(text, &local_end_text);
 196 
 197         if (errno == ERANGE) {
 198             /*
 199              * Overflow: strtod() returns +/- HUGE_VAL and sets errno to
 200              *           ERANGE
 201              *
 202              * Underflow: strtod() returns "a value whose magnitude is
 203              *            no greater than the smallest normalized
 204              *            positive" double. Whether ERANGE is set is
 205              *            implementation-defined.
 206              */
 207             const char *over_under;
 208 
 209             if (fabs(*result) > DBL_MIN) {
 210                 rc = EOVERFLOW;
 211                 over_under = "over";
 212             } else {
 213                 rc = pcmk_rc_underflow;
 214                 over_under = "under";
 215             }
 216 
 217             crm_debug("Floating-point value parsed from '%s' would %sflow "
 218                       "(using %g instead)", text, over_under, *result);
 219 
 220         } else if (errno != 0) {
 221             rc = errno;
 222             // strtod() set *result = 0 on parse failure
 223             *result = PCMK__PARSE_DBL_DEFAULT;
 224 
 225             crm_debug("Could not parse floating-point value from '%s' (using "
 226                       "%.1f instead): %s", text, PCMK__PARSE_DBL_DEFAULT,
 227                       pcmk_rc_str(rc));
 228 
 229         } else if (local_end_text == text) {
 230             // errno == 0, but nothing was parsed
 231             rc = EINVAL;
 232             *result = PCMK__PARSE_DBL_DEFAULT;
 233 
 234             crm_debug("Could not parse floating-point value from '%s' (using "
 235                       "%.1f instead): No digits found", text,
 236                       PCMK__PARSE_DBL_DEFAULT);
 237 
 238         } else if (fabs(*result) <= DBL_MIN) {
 239             /*
 240              * errno == 0 and text was parsed, but value might have
 241              * underflowed.
 242              *
 243              * ERANGE might not be set for underflow. Check magnitude
 244              * of *result, but also make sure the input number is not
 245              * actually zero (0 <= DBL_MIN is not underflow).
 246              *
 247              * This check must come last. A parse failure in strtod()
 248              * also sets *result == 0, so a parse failure would match
 249              * this test condition prematurely.
 250              */
 251             for (const char *p = text; p != local_end_text; p++) {
 252                 if (strchr("0.eE", *p) == NULL) {
 253                     rc = pcmk_rc_underflow;
 254                     crm_debug("Floating-point value parsed from '%s' would "
 255                               "underflow (using %g instead)", text, *result);
 256                     break;
 257                 }
 258             }
 259 
 260         } else {
 261             crm_trace("Floating-point value parsed successfully from "
 262                       "'%s': %g", text, *result);
 263         }
 264 
 265         if ((end_text == NULL) && !pcmk__str_empty(local_end_text)) {
 266             crm_debug("Characters left over after parsing '%s': '%s'",
 267                       text, local_end_text);
 268         }
 269     }
 270 
 271     if (end_text != NULL) {
 272         *end_text = local_end_text;
 273     }
 274 
 275     return rc;
 276 }
 277 
 278 /*!
 279  * \internal
 280  * \brief Parse a guint from a string stored in a hash table
 281  *
 282  * \param[in]  table        Hash table to search
 283  * \param[in]  key          Hash table key to use to retrieve string
 284  * \param[in]  default_val  What to use if key has no entry in table
 285  * \param[out] result       If not NULL, where to store parsed integer
 286  *
 287  * \return Standard Pacemaker return code
 288  */
 289 int
 290 pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val,
     /* [previous][next][first][last][top][bottom][index][help] */
 291                       guint *result)
 292 {
 293     const char *value;
 294     long long value_ll;
 295 
 296     CRM_CHECK((table != NULL) && (key != NULL), return EINVAL);
 297 
 298     value = g_hash_table_lookup(table, key);
 299     if (value == NULL) {
 300         if (result != NULL) {
 301             *result = default_val;
 302         }
 303         return pcmk_rc_ok;
 304     }
 305 
 306     errno = 0;
 307     value_ll = crm_parse_ll(value, NULL);
 308     if (errno != 0) {
 309         return errno; // Message already logged
 310     }
 311     if ((value_ll < 0) || (value_ll > G_MAXUINT)) {
 312         crm_warn("Could not parse non-negative integer from %s", value);
 313         return ERANGE;
 314     }
 315 
 316     if (result != NULL) {
 317         *result = (guint) value_ll;
 318     }
 319     return pcmk_rc_ok;
 320 }
 321 
 322 #ifndef NUMCHARS
 323 #  define       NUMCHARS        "0123456789."
 324 #endif
 325 
 326 #ifndef WHITESPACE
 327 #  define       WHITESPACE      " \t\n\r\f"
 328 #endif
 329 
 330 /*!
 331  * \brief Parse a time+units string and return milliseconds equivalent
 332  *
 333  * \param[in] input  String with a number and units (optionally with whitespace
 334  *                   before and/or after the number)
 335  *
 336  * \return Milliseconds corresponding to string expression, or
 337  *         PCMK__PARSE_INT_DEFAULT on error
 338  */
 339 long long
 340 crm_get_msec(const char *input)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342     const char *num_start = NULL;
 343     const char *units;
 344     long long multiplier = 1000;
 345     long long divisor = 1;
 346     long long msec = PCMK__PARSE_INT_DEFAULT;
 347     size_t num_len = 0;
 348     char *end_text = NULL;
 349 
 350     if (input == NULL) {
 351         return PCMK__PARSE_INT_DEFAULT;
 352     }
 353 
 354     num_start = input + strspn(input, WHITESPACE);
 355     num_len = strspn(num_start, NUMCHARS);
 356     if (num_len < 1) {
 357         return PCMK__PARSE_INT_DEFAULT;
 358     }
 359     units = num_start + num_len;
 360     units += strspn(units, WHITESPACE);
 361 
 362     if (!strncasecmp(units, "ms", 2) || !strncasecmp(units, "msec", 4)) {
 363         multiplier = 1;
 364         divisor = 1;
 365     } else if (!strncasecmp(units, "us", 2) || !strncasecmp(units, "usec", 4)) {
 366         multiplier = 1;
 367         divisor = 1000;
 368     } else if (!strncasecmp(units, "s", 1) || !strncasecmp(units, "sec", 3)) {
 369         multiplier = 1000;
 370         divisor = 1;
 371     } else if (!strncasecmp(units, "m", 1) || !strncasecmp(units, "min", 3)) {
 372         multiplier = 60 * 1000;
 373         divisor = 1;
 374     } else if (!strncasecmp(units, "h", 1) || !strncasecmp(units, "hr", 2)) {
 375         multiplier = 60 * 60 * 1000;
 376         divisor = 1;
 377     } else if ((*units != EOS) && (*units != '\n') && (*units != '\r')) {
 378         return PCMK__PARSE_INT_DEFAULT;
 379     }
 380 
 381     scan_ll(num_start, &msec, &end_text);
 382     if (msec > (LLONG_MAX / multiplier)) {
 383         // Arithmetics overflow while multiplier/divisor mutually exclusive
 384         return LLONG_MAX;
 385     }
 386     msec *= multiplier;
 387     msec /= divisor;
 388     return msec;
 389 }
 390 
 391 gboolean
 392 crm_is_true(const char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
 393 {
 394     gboolean ret = FALSE;
 395 
 396     if (s != NULL) {
 397         crm_str_to_boolean(s, &ret);
 398     }
 399     return ret;
 400 }
 401 
 402 int
 403 crm_str_to_boolean(const char *s, int *ret)
     /* [previous][next][first][last][top][bottom][index][help] */
 404 {
 405     if (s == NULL) {
 406         return -1;
 407 
 408     } else if (strcasecmp(s, "true") == 0
 409                || strcasecmp(s, "on") == 0
 410                || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) {
 411         *ret = TRUE;
 412         return 1;
 413 
 414     } else if (strcasecmp(s, "false") == 0
 415                || strcasecmp(s, "off") == 0
 416                || strcasecmp(s, "no") == 0 || strcasecmp(s, "n") == 0 || strcasecmp(s, "0") == 0) {
 417         *ret = FALSE;
 418         return 1;
 419     }
 420     return -1;
 421 }
 422 
 423 char *
 424 crm_strip_trailing_newline(char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426     int len;
 427 
 428     if (str == NULL) {
 429         return str;
 430     }
 431 
 432     for (len = strlen(str) - 1; len >= 0 && str[len] == '\n'; len--) {
 433         str[len] = '\0';
 434     }
 435 
 436     return str;
 437 }
 438 
 439 /*!
 440  * \brief Check whether a string starts with a certain sequence
 441  *
 442  * \param[in] str    String to check
 443  * \param[in] prefix Sequence to match against beginning of \p str
 444  *
 445  * \return \c true if \p str begins with match, \c false otherwise
 446  * \note This is equivalent to !strncmp(s, prefix, strlen(prefix))
 447  *       but is likely less efficient when prefix is a string literal
 448  *       if the compiler optimizes away the strlen() at compile time,
 449  *       and more efficient otherwise.
 450  */
 451 bool
 452 pcmk__starts_with(const char *str, const char *prefix)
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454     const char *s = str;
 455     const char *p = prefix;
 456 
 457     if (!s || !p) {
 458         return false;
 459     }
 460     while (*s && *p) {
 461         if (*s++ != *p++) {
 462             return false;
 463         }
 464     }
 465     return (*p == 0);
 466 }
 467 
 468 static inline bool
 469 ends_with(const char *s, const char *match, bool as_extension)
     /* [previous][next][first][last][top][bottom][index][help] */
 470 {
 471     if (pcmk__str_empty(match)) {
 472         return true;
 473     } else if (s == NULL) {
 474         return false;
 475     } else {
 476         size_t slen, mlen;
 477 
 478         /* Besides as_extension, we could also check
 479            !strchr(&match[1], match[0]) but that would be inefficient.
 480          */
 481         if (as_extension) {
 482             s = strrchr(s, match[0]);
 483             return (s == NULL)? false : !strcmp(s, match);
 484         }
 485 
 486         mlen = strlen(match);
 487         slen = strlen(s);
 488         return ((slen >= mlen) && !strcmp(s + slen - mlen, match));
 489     }
 490 }
 491 
 492 /*!
 493  * \internal
 494  * \brief Check whether a string ends with a certain sequence
 495  *
 496  * \param[in] s      String to check
 497  * \param[in] match  Sequence to match against end of \p s
 498  *
 499  * \return \c true if \p s ends case-sensitively with match, \c false otherwise
 500  * \note pcmk__ends_with_ext() can be used if the first character of match
 501  *       does not recur in match.
 502  */
 503 bool
 504 pcmk__ends_with(const char *s, const char *match)
     /* [previous][next][first][last][top][bottom][index][help] */
 505 {
 506     return ends_with(s, match, false);
 507 }
 508 
 509 /*!
 510  * \internal
 511  * \brief Check whether a string ends with a certain "extension"
 512  *
 513  * \param[in] s      String to check
 514  * \param[in] match  Extension to match against end of \p s, that is,
 515  *                   its first character must not occur anywhere
 516  *                   in the rest of that very sequence (example: file
 517  *                   extension where the last dot is its delimiter,
 518  *                   e.g., ".html"); incorrect results may be
 519  *                   returned otherwise.
 520  *
 521  * \return \c true if \p s ends (verbatim, i.e., case sensitively)
 522  *         with "extension" designated as \p match (including empty
 523  *         string), \c false otherwise
 524  *
 525  * \note Main incentive to prefer this function over \c pcmk__ends_with()
 526  *       where possible is the efficiency (at the cost of added
 527  *       restriction on \p match as stated; the complexity class
 528  *       remains the same, though: BigO(M+N) vs. BigO(M+2N)).
 529  */
 530 bool
 531 pcmk__ends_with_ext(const char *s, const char *match)
     /* [previous][next][first][last][top][bottom][index][help] */
 532 {
 533     return ends_with(s, match, true);
 534 }
 535 
 536 /*
 537  * This re-implements g_str_hash as it was prior to glib2-2.28:
 538  *
 539  * https://gitlab.gnome.org/GNOME/glib/commit/354d655ba8a54b754cb5a3efb42767327775696c
 540  *
 541  * Note that the new g_str_hash is presumably a *better* hash (it's actually
 542  * a correct implementation of DJB's hash), but we need to preserve existing
 543  * behaviour, because the hash key ultimately determines the "sort" order
 544  * when iterating through GHashTables, which affects allocation of scores to
 545  * clone instances when iterating through rsc->allowed_nodes.  It (somehow)
 546  * also appears to have some minor impact on the ordering of a few
 547  * pseudo_event IDs in the transition graph.
 548  */
 549 guint
 550 g_str_hash_traditional(gconstpointer v)
     /* [previous][next][first][last][top][bottom][index][help] */
 551 {
 552     const signed char *p;
 553     guint32 h = 0;
 554 
 555     for (p = v; *p != '\0'; p++)
 556         h = (h << 5) - h + *p;
 557 
 558     return h;
 559 }
 560 
 561 /* used with hash tables where case does not matter */
 562 gboolean
 563 crm_strcase_equal(gconstpointer a, gconstpointer b)
     /* [previous][next][first][last][top][bottom][index][help] */
 564 {
 565     return pcmk__str_eq((const char *)a, (const char *)b, pcmk__str_casei);
 566 }
 567 
 568 guint
 569 crm_strcase_hash(gconstpointer v)
     /* [previous][next][first][last][top][bottom][index][help] */
 570 {
 571     const signed char *p;
 572     guint32 h = 0;
 573 
 574     for (p = v; *p != '\0'; p++)
 575         h = (h << 5) - h + g_ascii_tolower(*p);
 576 
 577     return h;
 578 }
 579 
 580 static void
 581 copy_str_table_entry(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 582 {
 583     if (key && value && user_data) {
 584         g_hash_table_insert((GHashTable*)user_data, strdup(key), strdup(value));
 585     }
 586 }
 587 
 588 GHashTable *
 589 crm_str_table_dup(GHashTable *old_table)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591     GHashTable *new_table = NULL;
 592 
 593     if (old_table) {
 594         new_table = crm_str_table_new();
 595         g_hash_table_foreach(old_table, copy_str_table_entry, new_table);
 596     }
 597     return new_table;
 598 }
 599 
 600 /*!
 601  * \internal
 602  * \brief Add a word to a string list of words
 603  *
 604  * \param[in,out] list       Pointer to current string list (may not be NULL)
 605  * \param[in,out] len        If not NULL, must be set to length of \p list,
 606  *                           and will be updated to new length of \p list
 607  * \param[in]     word       String to add to \p list (\p list will be
 608  *                           unchanged if this is NULL or the empty string)
 609  * \param[in]     separator  String to separate words in \p list
 610  *                           (a space will be used if this is NULL)
 611  *
 612  * \note This dynamically reallocates \p list as needed. \p word may contain
 613  *       \p separator, though that would be a bad idea if the string needs to be
 614  *       parsed later.
 615  */
 616 void
 617 pcmk__add_separated_word(char **list, size_t *len, const char *word,
     /* [previous][next][first][last][top][bottom][index][help] */
 618                          const char *separator)
 619 {
 620     size_t orig_len, new_len;
 621 
 622     CRM_ASSERT(list != NULL);
 623 
 624     if (pcmk__str_empty(word)) {
 625         return;
 626     }
 627 
 628     // Use provided length, or calculate it if not available
 629     orig_len = (len != NULL)? *len : ((*list == NULL)? 0 : strlen(*list));
 630 
 631     // Don't add a separator before the first word in the list
 632     if (orig_len == 0) {
 633         separator = "";
 634 
 635     // Default to space-separated
 636     } else if (separator == NULL) {
 637         separator = " ";
 638     }
 639 
 640     new_len = orig_len + strlen(separator) + strlen(word);
 641     if (len != NULL) {
 642         *len = new_len;
 643     }
 644 
 645     // +1 for null terminator
 646     *list = pcmk__realloc(*list, new_len + 1);
 647     sprintf(*list + orig_len, "%s%s", separator, word);
 648 }
 649 
 650 /*!
 651  * \internal
 652  * \brief Compress data
 653  *
 654  * \param[in]  data        Data to compress
 655  * \param[in]  length      Number of characters of data to compress
 656  * \param[in]  max         Maximum size of compressed data (or 0 to estimate)
 657  * \param[out] result      Where to store newly allocated compressed result
 658  * \param[out] result_len  Where to store actual compressed length of result
 659  *
 660  * \return Standard Pacemaker return code
 661  */
 662 int
 663 pcmk__compress(const char *data, unsigned int length, unsigned int max,
     /* [previous][next][first][last][top][bottom][index][help] */
 664                char **result, unsigned int *result_len)
 665 {
 666     int rc;
 667     char *compressed = NULL;
 668     char *uncompressed = strdup(data);
 669 #ifdef CLOCK_MONOTONIC
 670     struct timespec after_t;
 671     struct timespec before_t;
 672 #endif
 673 
 674     if (max == 0) {
 675         max = (length * 1.01) + 601; // Size guaranteed to hold result
 676     }
 677 
 678 #ifdef CLOCK_MONOTONIC
 679     clock_gettime(CLOCK_MONOTONIC, &before_t);
 680 #endif
 681 
 682     compressed = calloc((size_t) max, sizeof(char));
 683     CRM_ASSERT(compressed);
 684 
 685     *result_len = max;
 686     rc = BZ2_bzBuffToBuffCompress(compressed, result_len, uncompressed, length,
 687                                   CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK);
 688     free(uncompressed);
 689     if (rc != BZ_OK) {
 690         crm_err("Compression of %d bytes failed: %s " CRM_XS " bzerror=%d",
 691                 length, bz2_strerror(rc), rc);
 692         free(compressed);
 693         return pcmk_rc_error;
 694     }
 695 
 696 #ifdef CLOCK_MONOTONIC
 697     clock_gettime(CLOCK_MONOTONIC, &after_t);
 698 
 699     crm_trace("Compressed %d bytes into %d (ratio %d:1) in %.0fms",
 700              length, *result_len, length / (*result_len),
 701              (after_t.tv_sec - before_t.tv_sec) * 1000 +
 702              (after_t.tv_nsec - before_t.tv_nsec) / 1e6);
 703 #else
 704     crm_trace("Compressed %d bytes into %d (ratio %d:1)",
 705              length, *result_len, length / (*result_len));
 706 #endif
 707 
 708     *result = compressed;
 709     return pcmk_rc_ok;
 710 }
 711 
 712 char *
 713 crm_strdup_printf(char const *format, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 714 {
 715     va_list ap;
 716     int len = 0;
 717     char *string = NULL;
 718 
 719     va_start(ap, format);
 720     len = vasprintf (&string, format, ap);
 721     CRM_ASSERT(len > 0);
 722     va_end(ap);
 723     return string;
 724 }
 725 
 726 int
 727 pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
     /* [previous][next][first][last][top][bottom][index][help] */
 728 {
 729     char *remainder = NULL;
 730 
 731     CRM_ASSERT(start != NULL && end != NULL);
 732 
 733     *start = PCMK__PARSE_INT_DEFAULT;
 734     *end = PCMK__PARSE_INT_DEFAULT;
 735 
 736     crm_trace("Attempting to decode: [%s]", srcstring);
 737     if (pcmk__str_empty(srcstring) || !strcmp(srcstring, "-")) {
 738         return pcmk_rc_unknown_format;
 739     }
 740 
 741     /* String starts with a dash, so this is either a range with
 742      * no beginning or garbage.
 743      * */
 744     if (*srcstring == '-') {
 745         int rc = scan_ll(srcstring+1, end, &remainder);
 746 
 747         if (rc != pcmk_rc_ok || *remainder != '\0') {
 748             return pcmk_rc_unknown_format;
 749         } else {
 750             return pcmk_rc_ok;
 751         }
 752     }
 753 
 754     if (scan_ll(srcstring, start, &remainder) != pcmk_rc_ok) {
 755         return pcmk_rc_unknown_format;
 756     }
 757 
 758     if (*remainder && *remainder == '-') {
 759         if (*(remainder+1)) {
 760             char *more_remainder = NULL;
 761             int rc = scan_ll(remainder+1, end, &more_remainder);
 762 
 763             if (rc != pcmk_rc_ok || *more_remainder != '\0') {
 764                 return pcmk_rc_unknown_format;
 765             }
 766         }
 767     } else if (*remainder && *remainder != '-') {
 768         *start = PCMK__PARSE_INT_DEFAULT;
 769         return pcmk_rc_unknown_format;
 770     } else {
 771         /* The input string contained only one number.  Set start and end
 772          * to the same value and return pcmk_rc_ok.  This gives the caller
 773          * a way to tell this condition apart from a range with no end.
 774          */
 775         *end = *start;
 776     }
 777 
 778     return pcmk_rc_ok;
 779 }
 780 
 781 /*!
 782  * \internal
 783  * \brief Find a string in a list of strings
 784  *
 785  * Search \p lst for \p s, taking case into account.  As a special case,
 786  * if "*" is the only element of \p lst, the search is successful.
 787  *
 788  * \param[in]  lst  List to search
 789  * \param[in]  s    String to search for
 790  *
 791  * \return \c TRUE if \p s is in \p lst, or \c FALSE otherwise
 792  */
 793 gboolean
 794 pcmk__str_in_list(GList *lst, const gchar *s)
     /* [previous][next][first][last][top][bottom][index][help] */
 795 {
 796     if (lst == NULL) {
 797         return FALSE;
 798     }
 799 
 800     if (strcmp(lst->data, "*") == 0 && lst->next == NULL) {
 801         return TRUE;
 802     }
 803 
 804     return g_list_find_custom(lst, s, (GCompareFunc) strcmp) != NULL;
 805 }
 806 
 807 static bool
 808 str_any_of(bool casei, const char *s, va_list args)
     /* [previous][next][first][last][top][bottom][index][help] */
 809 {
 810     bool rc = false;
 811 
 812     if (s != NULL) {
 813         while (1) {
 814             const char *ele = va_arg(args, const char *);
 815 
 816             if (ele == NULL) {
 817                 break;
 818             } else if (pcmk__str_eq(s, ele,
 819                                     casei? pcmk__str_casei : pcmk__str_none)) {
 820                 rc = true;
 821                 break;
 822             }
 823         }
 824     }
 825     return rc;
 826 }
 827 
 828 /*!
 829  * \internal
 830  * \brief Is a string a member of a list of strings?
 831  *
 832  * \param[in]  s    String to search for in \p ...
 833  * \param[in]  ...  Strings to compare \p s against.  The final string
 834  *                  must be NULL.
 835  *
 836  * \note The comparison is done case-insensitively.  The function name is
 837  *       meant to be reminiscent of strcasecmp.
 838  *
 839  * \return \c true if \p s is in \p ..., or \c false otherwise
 840  */
 841 bool
 842 pcmk__strcase_any_of(const char *s, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 843 {
 844     va_list ap;
 845     bool rc;
 846 
 847     va_start(ap, s);
 848     rc = str_any_of(true, s, ap);
 849     va_end(ap);
 850     return rc;
 851 }
 852 
 853 /*!
 854  * \internal
 855  * \brief Is a string a member of a list of strings?
 856  *
 857  * \param[in]  s    String to search for in \p ...
 858  * \param[in]  ...  Strings to compare \p s against.  The final string
 859  *                  must be NULL.
 860  *
 861  * \note The comparison is done taking case into account.
 862  *
 863  * \return \c true if \p s is in \p ..., or \c false otherwise
 864  */
 865 bool
 866 pcmk__str_any_of(const char *s, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 867 {
 868     va_list ap;
 869     bool rc;
 870 
 871     va_start(ap, s);
 872     rc = str_any_of(false, s, ap);
 873     va_end(ap);
 874     return rc;
 875 }
 876 
 877 /*!
 878  * \internal
 879  * \brief Check whether a character is in any of a list of strings
 880  *
 881  * \param[in]   ch      Character (ASCII) to search for
 882  * \param[in]   ...     Strings to search. Final argument must be
 883  *                      \c NULL.
 884  *
 885  * \return  \c true if any of \p ... contain \p ch, \c false otherwise
 886  * \note    \p ... must contain at least one argument (\c NULL).
 887  */
 888 bool
 889 pcmk__char_in_any_str(int ch, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 890 {
 891     bool rc = false;
 892     va_list ap;
 893 
 894     /*
 895      * Passing a char to va_start() can generate compiler warnings,
 896      * so ch is declared as an int.
 897      */
 898     va_start(ap, ch);
 899 
 900     while (1) {
 901         const char *ele = va_arg(ap, const char *);
 902 
 903         if (ele == NULL) {
 904             break;
 905         } else if (strchr(ele, ch) != NULL) {
 906             rc = true;
 907             break;
 908         }
 909     }
 910 
 911     va_end(ap);
 912     return rc;
 913 }
 914 
 915 /*!
 916  * \brief Sort strings, with numeric portions sorted numerically
 917  *
 918  * Sort two strings case-insensitively like strcasecmp(), but with any numeric
 919  * portions of the string sorted numerically. This is particularly useful for
 920  * node names (for example, "node10" will sort higher than "node9" but lower
 921  * than "remotenode9").
 922  *
 923  * \param[in] s1  First string to compare (must not be NULL)
 924  * \param[in] s2  Second string to compare (must not be NULL)
 925  *
 926  * \retval -1 \p s1 comes before \p s2
 927  * \retval  0 \p s1 and \p s2 are equal
 928  * \retval  1 \p s1 comes after \p s2
 929  */
 930 int
 931 pcmk_numeric_strcasecmp(const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help] */
 932 {
 933     while (*s1 && *s2) {
 934         if (isdigit(*s1) && isdigit(*s2)) {
 935             // If node names contain a number, sort numerically
 936 
 937             char *end1 = NULL;
 938             char *end2 = NULL;
 939             long num1 = strtol(s1, &end1, 10);
 940             long num2 = strtol(s2, &end2, 10);
 941 
 942             // allow ordering e.g. 007 > 7
 943             size_t len1 = end1 - s1;
 944             size_t len2 = end2 - s2;
 945 
 946             if (num1 < num2) {
 947                 return -1;
 948             } else if (num1 > num2) {
 949                 return 1;
 950             } else if (len1 < len2) {
 951                 return -1;
 952             } else if (len1 > len2) {
 953                 return 1;
 954             }
 955             s1 = end1;
 956             s2 = end2;
 957         } else {
 958             // Compare non-digits case-insensitively
 959             int lower1 = tolower(*s1);
 960             int lower2 = tolower(*s2);
 961 
 962             if (lower1 < lower2) {
 963                 return -1;
 964             } else if (lower1 > lower2) {
 965                 return 1;
 966             }
 967             ++s1;
 968             ++s2;
 969         }
 970     }
 971     if (!*s1 && *s2) {
 972         return -1;
 973     } else if (*s1 && !*s2) {
 974         return 1;
 975     }
 976     return 0;
 977 }
 978 
 979 /*
 980  * \brief Sort strings.
 981  *
 982  * This is your one-stop function for string comparison.  By default, this
 983  * function works like g_strcmp0.  That is, like strcmp but a NULL string
 984  * sorts before a non-NULL string.
 985  *
 986  * Behavior can be changed with various flags:
 987  *
 988  * - pcmk__str_regex - The second string is a regular expression that the
 989  *                     first string will be matched against.
 990  * - pcmk__str_casei - By default, comparisons are done taking case into
 991  *                     account.  This flag makes comparisons case-insensitive.
 992  *                     This can be combined with pcmk__str_regex.
 993  * - pcmk__str_null_matches - If one string is NULL and the other is not,
 994  *                            still return 0.
 995  *
 996  * \param[in] s1    First string to compare
 997  * \param[in] s2    Second string to compare, or a regular expression to
 998  *                  match if pcmk__str_regex is set
 999  * \param[in] flags A bitfield of pcmk__str_flags to modify operation
1000  *
1001  * \retval -1 \p s1 is NULL or comes before \p s2
1002  * \retval  0 \p s1 and \p s2 are equal, or \p s1 is found in \p s2 if
1003  *            pcmk__str_regex is set
1004  * \retval  1 \p s2 is NULL or \p s1 comes after \p s2, or if \p s2
1005  *            is an invalid regular expression, or \p s1 was not found
1006  *            in \p s2 if pcmk__str_regex is set.
1007  */
1008 int
1009 pcmk__strcmp(const char *s1, const char *s2, uint32_t flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1010 {
1011     /* If this flag is set, the second string is a regex. */
1012     if (pcmk_is_set(flags, pcmk__str_regex)) {
1013         regex_t *r_patt = calloc(1, sizeof(regex_t));
1014         int reg_flags = REG_EXTENDED | REG_NOSUB;
1015         int regcomp_rc = 0;
1016         int rc = 0;
1017 
1018         if (s1 == NULL || s2 == NULL) {
1019             free(r_patt);
1020             return 1;
1021         }
1022 
1023         if (pcmk_is_set(flags, pcmk__str_casei)) {
1024             reg_flags |= REG_ICASE;
1025         }
1026         regcomp_rc = regcomp(r_patt, s2, reg_flags);
1027         if (regcomp_rc != 0) {
1028             rc = 1;
1029             crm_err("Bad regex '%s' for update: %s", s2, strerror(regcomp_rc));
1030         } else {
1031             rc = regexec(r_patt, s1, 0, NULL, 0);
1032 
1033             if (rc != 0) {
1034                 rc = 1;
1035             }
1036         }
1037 
1038         regfree(r_patt);
1039         free(r_patt);
1040         return rc;
1041     }
1042 
1043     /* If the strings are the same pointer, return 0 immediately. */
1044     if (s1 == s2) {
1045         return 0;
1046     }
1047 
1048     /* If this flag is set, return 0 if either (or both) of the input strings
1049      * are NULL.  If neither one is NULL, we need to continue and compare
1050      * them normally.
1051      */
1052     if (pcmk_is_set(flags, pcmk__str_null_matches)) {
1053         if (s1 == NULL || s2 == NULL) {
1054             return 0;
1055         }
1056     }
1057 
1058     /* Handle the cases where one is NULL and the str_null_matches flag is not set.
1059      * A NULL string always sorts to the beginning.
1060      */
1061     if (s1 == NULL) {
1062         return -1;
1063     } else if (s2 == NULL) {
1064         return 1;
1065     }
1066 
1067     if (pcmk_is_set(flags, pcmk__str_casei)) {
1068         return strcasecmp(s1, s2);
1069     } else {
1070         return strcmp(s1, s2);
1071     }
1072 }
1073 
1074 // Deprecated functions kept only for backward API compatibility
1075 
1076 gboolean safe_str_neq(const char *a, const char *b);
1077 
1078 gboolean crm_str_eq(const char *a, const char *b, gboolean use_case);
1079 
1080 //! \deprecated Use pcmk__str_eq() instead
1081 gboolean
1082 safe_str_neq(const char *a, const char *b)
     /* [previous][next][first][last][top][bottom][index][help] */
1083 {
1084     if (a == b) {
1085         return FALSE;
1086 
1087     } else if (a == NULL || b == NULL) {
1088         return TRUE;
1089 
1090     } else if (strcasecmp(a, b) == 0) {
1091         return FALSE;
1092     }
1093     return TRUE;
1094 }
1095 
1096 //! \deprecated Use pcmk__str_eq() instead
1097 gboolean
1098 crm_str_eq(const char *a, const char *b, gboolean use_case)
     /* [previous][next][first][last][top][bottom][index][help] */
1099 {
1100     if (use_case) {
1101         return g_strcmp0(a, b) == 0;
1102 
1103         /* TODO - Figure out which calls, if any, really need to be case independent */
1104     } else if (a == b) {
1105         return TRUE;
1106 
1107     } else if (a == NULL || b == NULL) {
1108         /* shouldn't be comparing NULLs */
1109         return FALSE;
1110 
1111     } else if (strcasecmp(a, b) == 0) {
1112         return TRUE;
1113     }
1114     return FALSE;
1115 }

/* [previous][next][first][last][top][bottom][index][help] */