root/lib/common/scores.c

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

DEFINITIONS

This source file includes following definitions.
  1. char2score
  2. pcmk_readable_score
  3. pcmk__add_scores
  4. score2char
  5. score2char_stack

   1 /*
   2  * Copyright 2004-2023 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 <stdio.h>      // snprintf(), NULL
  17 #include <string.h>     // strcpy(), strdup()
  18 #include <sys/types.h>  // size_t
  19 
  20 int pcmk__score_red = 0;
  21 int pcmk__score_green = 0;
  22 int pcmk__score_yellow = 0;
  23 
  24 /*!
  25  * \brief Get the integer value of a score string
  26  *
  27  * Given a string representation of a score, return the integer equivalent.
  28  * This accepts infinity strings as well as red, yellow, and green, and
  29  * bounds the result to +/-INFINITY.
  30  *
  31  * \param[in] score  Score as string
  32  *
  33  * \return Integer value corresponding to \p score
  34  */
  35 int
  36 char2score(const char *score)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38     if (score == NULL) {
  39         return 0;
  40 
  41     } else if (pcmk_str_is_minus_infinity(score)) {
  42         return -CRM_SCORE_INFINITY;
  43 
  44     } else if (pcmk_str_is_infinity(score)) {
  45         return CRM_SCORE_INFINITY;
  46 
  47     } else if (pcmk__str_eq(score, PCMK__VALUE_RED, pcmk__str_casei)) {
  48         return pcmk__score_red;
  49 
  50     } else if (pcmk__str_eq(score, PCMK__VALUE_YELLOW, pcmk__str_casei)) {
  51         return pcmk__score_yellow;
  52 
  53     } else if (pcmk__str_eq(score, PCMK__VALUE_GREEN, pcmk__str_casei)) {
  54         return pcmk__score_green;
  55 
  56     } else {
  57         long long score_ll;
  58 
  59         pcmk__scan_ll(score, &score_ll, 0LL);
  60         if (score_ll > CRM_SCORE_INFINITY) {
  61             return CRM_SCORE_INFINITY;
  62 
  63         } else if (score_ll < -CRM_SCORE_INFINITY) {
  64             return -CRM_SCORE_INFINITY;
  65 
  66         } else {
  67             return (int) score_ll;
  68         }
  69     }
  70 }
  71 
  72 /*!
  73  * \brief Return a displayable static string for a score value
  74  *
  75  * Given a score value, return a pointer to a static string representation of
  76  * the score suitable for log messages, output, etc.
  77  *
  78  * \param[in] score  Score to display
  79  *
  80  * \return Pointer to static memory containing string representation of \p score
  81  * \note Subsequent calls to this function will overwrite the returned value, so
  82  *       it should be used only in a local context such as a printf()-style
  83  *       statement.
  84  */
  85 const char *
  86 pcmk_readable_score(int score)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88     // The longest possible result is "-INFINITY"
  89     static char score_s[sizeof(CRM_MINUS_INFINITY_S)];
  90 
  91     if (score >= CRM_SCORE_INFINITY) {
  92         strcpy(score_s, CRM_INFINITY_S);
  93 
  94     } else if (score <= -CRM_SCORE_INFINITY) {
  95         strcpy(score_s, CRM_MINUS_INFINITY_S);
  96 
  97     } else {
  98         // Range is limited to +/-1000000, so no chance of overflow
  99         snprintf(score_s, sizeof(score_s), "%d", score);
 100     }
 101 
 102     return score_s;
 103 }
 104 
 105 /*!
 106  * \internal
 107  * \brief Add two scores, bounding to +/-INFINITY
 108  *
 109  * \param[in] score1  First score to add
 110  * \param[in] score2  Second score to add
 111  *
 112  * \note This function does not have context about what the scores mean, so it
 113  *       does not log any messages.
 114  */
 115 int
 116 pcmk__add_scores(int score1, int score2)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118     /* As long as CRM_SCORE_INFINITY is less than half of the maximum integer,
 119      * we can ignore the possibility of integer overflow.
 120      */
 121     int result = score1 + score2;
 122 
 123     // First handle the cases where one or both is infinite
 124     if ((score1 <= -CRM_SCORE_INFINITY) || (score2 <= -CRM_SCORE_INFINITY)) {
 125         return -CRM_SCORE_INFINITY;
 126     }
 127     if ((score1 >= CRM_SCORE_INFINITY) || (score2 >= CRM_SCORE_INFINITY)) {
 128         return CRM_SCORE_INFINITY;
 129     }
 130 
 131     // Bound result to infinity.
 132     if (result >= CRM_SCORE_INFINITY) {
 133         return CRM_SCORE_INFINITY;
 134     }
 135     if (result <= -CRM_SCORE_INFINITY) {
 136         return -CRM_SCORE_INFINITY;
 137     }
 138 
 139     return result;
 140 }
 141 
 142 // Deprecated functions kept only for backward API compatibility
 143 // LCOV_EXCL_START
 144 
 145 #include <crm/common/util_compat.h>
 146 
 147 char *
 148 score2char(int score)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150     char *result = strdup(pcmk_readable_score(score));
 151 
 152     CRM_ASSERT(result != NULL);
 153     return result;
 154 }
 155 
 156 char *
 157 score2char_stack(int score, char *buf, size_t len)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159     CRM_CHECK((buf != NULL) && (len >= sizeof(CRM_MINUS_INFINITY_S)),
 160               return NULL);
 161     strcpy(buf, pcmk_readable_score(score));
 162     return buf;
 163 }
 164 
 165 // LCOV_EXCL_STOP
 166 // End deprecated API

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