root/lib/common/scores.c

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

DEFINITIONS

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

   1 /*
   2  * Copyright 2004-2022 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 Convert an integer score to a string, using a provided buffer
  74  *
  75  * Store the string equivalent of a given integer score in a given string
  76  * buffer, using "INFINITY" and "-INFINITY" when appropriate.
  77  *
  78  * \param[in]  score  Integer score to convert
  79  * \param[out] buf    Where to store string representation of \p score
  80  * \param[in]  len    Size of \p buf (in bytes)
  81  *
  82  * \return \p buf (or NULL if \p len is too small)
  83  */
  84 char *
  85 score2char_stack(int score, char *buf, size_t len)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     CRM_CHECK((buf != NULL) && (len >= sizeof(CRM_MINUS_INFINITY_S)),
  88               return NULL);
  89 
  90     if (score >= CRM_SCORE_INFINITY) {
  91         strcpy(buf, CRM_INFINITY_S);
  92     } else if (score <= -CRM_SCORE_INFINITY) {
  93         strcpy(buf, CRM_MINUS_INFINITY_S);
  94     } else {
  95         snprintf(buf, len, "%d", score);
  96     }
  97     return buf;
  98 }
  99 
 100 /*!
 101  * \brief Return the string equivalent of an integer score
 102  *
 103  * Return the string equivalent of a given integer score, using "INFINITY" and
 104  * "-INFINITY" when appropriate.
 105  *
 106  * \param[in]  score  Integer score to convert
 107  *
 108  * \return Newly allocated string equivalent of \p score
 109  * \note The caller is responsible for freeing the return value. This function
 110  *       asserts on memory errors, so the return value can be assumed to be
 111  *       non-NULL.
 112  */
 113 char *
 114 score2char(int score)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116     char *result = NULL;
 117 
 118     if (score >= CRM_SCORE_INFINITY) {
 119         result = strdup(CRM_INFINITY_S);
 120         CRM_ASSERT(result != NULL);
 121 
 122     } else if (score <= -CRM_SCORE_INFINITY) {
 123         result = strdup(CRM_MINUS_INFINITY_S);
 124         CRM_ASSERT(result != NULL);
 125 
 126     } else {
 127         result = pcmk__itoa(score);
 128     }
 129     return result;
 130 }
 131 
 132 /*!
 133  * \internal
 134  * \brief Add two scores, bounding to +/-INFINITY
 135  *
 136  * \param[in] score1  First score to add
 137  * \param[in] score2  Second score to add
 138  */
 139 int
 140 pcmk__add_scores(int score1, int score2)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142     int result = score1 + score2;
 143 
 144     // First handle the cases where one or both is infinite
 145 
 146     if (score1 <= -CRM_SCORE_INFINITY) {
 147 
 148         if (score2 <= -CRM_SCORE_INFINITY) {
 149             crm_trace("-INFINITY + -INFINITY = -INFINITY");
 150         } else if (score2 >= CRM_SCORE_INFINITY) {
 151             crm_trace("-INFINITY + +INFINITY = -INFINITY");
 152         } else {
 153             crm_trace("-INFINITY + %d = -INFINITY", score2);
 154         }
 155 
 156         return -CRM_SCORE_INFINITY;
 157 
 158     } else if (score2 <= -CRM_SCORE_INFINITY) {
 159 
 160         if (score1 >= CRM_SCORE_INFINITY) {
 161             crm_trace("+INFINITY + -INFINITY = -INFINITY");
 162         } else {
 163             crm_trace("%d + -INFINITY = -INFINITY", score1);
 164         }
 165 
 166         return -CRM_SCORE_INFINITY;
 167 
 168     } else if (score1 >= CRM_SCORE_INFINITY) {
 169 
 170         if (score2 >= CRM_SCORE_INFINITY) {
 171             crm_trace("+INFINITY + +INFINITY = +INFINITY");
 172         } else {
 173             crm_trace("+INFINITY + %d = +INFINITY", score2);
 174         }
 175 
 176         return CRM_SCORE_INFINITY;
 177 
 178     } else if (score2 >= CRM_SCORE_INFINITY) {
 179         crm_trace("%d + +INFINITY = +INFINITY", score1);
 180         return CRM_SCORE_INFINITY;
 181     }
 182 
 183     /* As long as CRM_SCORE_INFINITY is less than half of the maximum integer,
 184      * we can ignore the possibility of integer overflow
 185      */
 186 
 187     // Bound result to infinity
 188 
 189     if (result >= CRM_SCORE_INFINITY) {
 190         crm_trace("%d + %d = +INFINITY", score1, score2);
 191         return CRM_SCORE_INFINITY;
 192 
 193     } else if (result <= -CRM_SCORE_INFINITY) {
 194         crm_trace("%d + %d = -INFINITY", score1, score2);
 195         return -CRM_SCORE_INFINITY;
 196     }
 197 
 198     crm_trace("%d + %d = %d", score1, score2, result);
 199     return result;
 200 }

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