root/include/crm/common/strings_internal.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. pcmk__s
  2. pcmk__intkey_table
  3. pcmk__intkey_table_insert
  4. pcmk__intkey_table_lookup
  5. pcmk__intkey_table_remove
  6. pcmk__g_strcat
  7. pcmk__add_word
  8. pcmk__str_empty
  9. pcmk__itoa
  10. pcmk__ftoa
  11. pcmk__ttoa
  12. pcmk__btoa

   1 /*
   2  * Copyright 2015-2024 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 #ifndef PCMK__STRINGS_INTERNAL__H
  11 #define PCMK__STRINGS_INTERNAL__H
  12 
  13 #include <stdbool.h>            // bool
  14 
  15 #include <glib.h>               // guint, GList, GHashTable
  16 
  17 /* internal constants for generic string functions (from strings.c) */
  18 
  19 #define PCMK__PARSE_INT_DEFAULT -1
  20 #define PCMK__PARSE_DBL_DEFAULT -1.0
  21 
  22 /* internal generic string functions (from strings.c) */
  23 
  24 enum pcmk__str_flags {
  25     pcmk__str_none          = 0,
  26     pcmk__str_casei         = 1 << 0,
  27     pcmk__str_null_matches  = 1 << 1,
  28     pcmk__str_regex         = 1 << 2,
  29     pcmk__str_star_matches  = 1 << 3,
  30 };
  31 
  32 int pcmk__scan_double(const char *text, double *result,
  33                       const char *default_text, char **end_text);
  34 int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val,
  35                           guint *result);
  36 bool pcmk__starts_with(const char *str, const char *prefix);
  37 bool pcmk__ends_with(const char *s, const char *match);
  38 bool pcmk__ends_with_ext(const char *s, const char *match);
  39 char *pcmk__trim(char *str);
  40 void pcmk__add_separated_word(GString **list, size_t init_size,
  41                               const char *word, const char *separator);
  42 int pcmk__compress(const char *data, unsigned int length, unsigned int max,
  43                    char **result, unsigned int *result_len);
  44 
  45 int pcmk__scan_ll(const char *text, long long *result, long long default_value);
  46 int pcmk__scan_min_int(const char *text, int *result, int minimum);
  47 int pcmk__scan_port(const char *text, int *port);
  48 int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end);
  49 
  50 GHashTable *pcmk__strkey_table(GDestroyNotify key_destroy_func,
  51                                GDestroyNotify value_destroy_func);
  52 GHashTable *pcmk__strikey_table(GDestroyNotify key_destroy_func,
  53                                 GDestroyNotify value_destroy_func);
  54 GHashTable *pcmk__str_table_dup(GHashTable *old_table);
  55 void pcmk__insert_dup(GHashTable *table, const char *name, const char *value);
  56 
  57 /*!
  58  * \internal
  59  * \brief Get a string value with a default if NULL
  60  *
  61  * \param[in] s              String to return if non-NULL
  62  * \param[in] default_value  String (or NULL) to return if \p s is NULL
  63  *
  64  * \return \p s if \p s is non-NULL, otherwise \p default_value
  65  */
  66 static inline const char *
  67 pcmk__s(const char *s, const char *default_value)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69     return (s == NULL)? default_value : s;
  70 }
  71 
  72 /*!
  73  * \internal
  74  * \brief Create a hash table with integer keys
  75  *
  76  * \param[in] value_destroy_func  Function to free a value
  77  *
  78  * \return Newly allocated hash table
  79  * \note It is the caller's responsibility to free the result, using
  80  *       g_hash_table_destroy().
  81  */
  82 static inline GHashTable *
  83 pcmk__intkey_table(GDestroyNotify value_destroy_func)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     return g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
  86                                  value_destroy_func);
  87 }
  88 
  89 /*!
  90  * \internal
  91  * \brief Insert a value into a hash table with integer keys
  92  *
  93  * \param[in,out] hash_table  Table to insert into
  94  * \param[in]     key         Integer key to insert
  95  * \param[in]     value       Value to insert
  96  *
  97  * \return Whether the key/value was already in the table
  98  * \note This has the same semantics as g_hash_table_insert(). If the key
  99  *       already exists in the table, the old value is freed and replaced.
 100  */
 101 static inline gboolean
 102 pcmk__intkey_table_insert(GHashTable *hash_table, int key, gpointer value)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104     return g_hash_table_insert(hash_table, GINT_TO_POINTER(key), value);
 105 }
 106 
 107 /*!
 108  * \internal
 109  * \brief Look up a value in a hash table with integer keys
 110  *
 111  * \param[in] hash_table  Table to check
 112  * \param[in] key         Integer key to look for
 113  *
 114  * \return Value in table for \key (or NULL if not found)
 115  */
 116 static inline gpointer
 117 pcmk__intkey_table_lookup(GHashTable *hash_table, int key)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119     return g_hash_table_lookup(hash_table, GINT_TO_POINTER(key));
 120 }
 121 
 122 /*!
 123  * \internal
 124  * \brief Remove a key/value from a hash table with integer keys
 125  *
 126  * \param[in,out] hash_table  Table to modify
 127  * \param[in]     key         Integer key of entry to remove
 128  *
 129  * \return Whether \p key was found and removed from \p hash_table
 130  */
 131 static inline gboolean
 132 pcmk__intkey_table_remove(GHashTable *hash_table, int key)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134     return g_hash_table_remove(hash_table, GINT_TO_POINTER(key));
 135 }
 136 
 137 gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags);
 138 
 139 bool pcmk__strcase_any_of(const char *s, ...) G_GNUC_NULL_TERMINATED;
 140 bool pcmk__str_any_of(const char *s, ...) G_GNUC_NULL_TERMINATED;
 141 bool pcmk__char_in_any_str(int ch, ...) G_GNUC_NULL_TERMINATED;
 142 
 143 int pcmk__strcmp(const char *s1, const char *s2, uint32_t flags);
 144 int pcmk__numeric_strcasecmp(const char *s1, const char *s2);
 145 
 146 char *pcmk__str_copy_as(const char *file, const char *function, uint32_t line,
 147                         const char *str);
 148 
 149 /*!
 150  * \internal
 151  * \brief Copy a string, asserting on failure
 152  *
 153  * \param[in] str  String to copy (can be \c NULL)
 154  *
 155  * \return Newly allocated copy of \p str, or \c NULL if \p str is \c NULL
 156  *
 157  * \note The caller is responsible for freeing the return value using \c free().
 158  */
 159 #define pcmk__str_copy(str) pcmk__str_copy_as(__FILE__, __func__, __LINE__, str)
 160 
 161 void pcmk__str_update(char **str, const char *value);
 162 
 163 void pcmk__g_strcat(GString *buffer, ...) G_GNUC_NULL_TERMINATED;
     /* [previous][next][first][last][top][bottom][index][help] */
 164 
 165 static inline bool
 166 pcmk__str_eq(const char *s1, const char *s2, uint32_t flags)
 167 {
 168     return pcmk__strcmp(s1, s2, flags) == 0;
 169 }
 170 
 171 // Like pcmk__add_separated_word() but using a space as separator
 172 static inline void
 173 pcmk__add_word(GString **list, size_t init_size, const char *word)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175     return pcmk__add_separated_word(list, init_size, word, " ");
 176 }
 177 
 178 /* Correctly displaying singular or plural is complicated; consider "1 node has"
 179  * vs. "2 nodes have". A flexible solution is to pluralize entire strings, e.g.
 180  *
 181  * if (a == 1) {
 182  *     crm_info("singular message"):
 183  * } else {
 184  *     crm_info("plural message");
 185  * }
 186  *
 187  * though even that's not sufficient for all languages besides English (if we
 188  * ever desire to do translations of output and log messages). But the following
 189  * convenience macros are "good enough" and more concise for many cases.
 190  */
 191 
 192 /* Example:
 193  * crm_info("Found %d %s", nentries,
 194  *          pcmk__plural_alt(nentries, "entry", "entries"));
 195  */
 196 #define pcmk__plural_alt(i, s1, s2) (((i) == 1)? (s1) : (s2))
 197 
 198 // Example: crm_info("Found %d node%s", nnodes, pcmk__plural_s(nnodes));
 199 #define pcmk__plural_s(i) pcmk__plural_alt(i, "", "s")
 200 
 201 static inline int
 202 pcmk__str_empty(const char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     return (s == NULL) || (s[0] == '\0');
 205 }
 206 
 207 static inline char *
 208 pcmk__itoa(int an_int)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210     return crm_strdup_printf("%d", an_int);
 211 }
 212 
 213 static inline char *
 214 pcmk__ftoa(double a_float)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216     return crm_strdup_printf("%f", a_float);
 217 }
 218 
 219 static inline char *
 220 pcmk__ttoa(time_t epoch_time)
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222     return crm_strdup_printf("%lld", (long long) epoch_time);
 223 }
 224 
 225 // note this returns const not allocated
 226 static inline const char *
 227 pcmk__btoa(bool condition)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229     return condition? PCMK_VALUE_TRUE : PCMK_VALUE_FALSE;
 230 }
 231 
 232 #endif /* PCMK__STRINGS_INTERNAL__H */

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