Line data Source code
1 : /* 2 : * Copyright 2004-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 : #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 319 : char2score(const char *score) 37 : { 38 319 : if (score == NULL) { 39 231 : return 0; 40 : 41 88 : } else if (pcmk_str_is_minus_infinity(score)) { 42 7 : return -PCMK_SCORE_INFINITY; 43 : 44 81 : } else if (pcmk_str_is_infinity(score)) { 45 2 : return PCMK_SCORE_INFINITY; 46 : 47 79 : } else if (pcmk__str_eq(score, PCMK_VALUE_RED, pcmk__str_casei)) { 48 2 : return pcmk__score_red; 49 : 50 77 : } else if (pcmk__str_eq(score, PCMK_VALUE_YELLOW, pcmk__str_casei)) { 51 2 : return pcmk__score_yellow; 52 : 53 75 : } else if (pcmk__str_eq(score, PCMK_VALUE_GREEN, pcmk__str_casei)) { 54 2 : return pcmk__score_green; 55 : 56 : } else { 57 : long long score_ll; 58 : 59 73 : pcmk__scan_ll(score, &score_ll, 0LL); 60 73 : if (score_ll > PCMK_SCORE_INFINITY) { 61 2 : return PCMK_SCORE_INFINITY; 62 : 63 71 : } else if (score_ll < -PCMK_SCORE_INFINITY) { 64 1 : return -PCMK_SCORE_INFINITY; 65 : 66 : } else { 67 70 : 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 5 : pcmk_readable_score(int score) 87 : { 88 : // The longest possible result is "-INFINITY" 89 : static char score_s[sizeof(PCMK_VALUE_MINUS_INFINITY)]; 90 : 91 5 : if (score >= PCMK_SCORE_INFINITY) { 92 1 : strcpy(score_s, PCMK_VALUE_INFINITY); 93 : 94 4 : } else if (score <= -PCMK_SCORE_INFINITY) { 95 1 : strcpy(score_s, PCMK_VALUE_MINUS_INFINITY); 96 : 97 : } else { 98 : // Range is limited to +/-1000000, so no chance of overflow 99 3 : snprintf(score_s, sizeof(score_s), "%d", score); 100 : } 101 : 102 5 : 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 588 : pcmk__add_scores(int score1, int score2) 117 : { 118 : /* As long as PCMK_SCORE_INFINITY is less than half of the maximum integer, 119 : * we can ignore the possibility of integer overflow. 120 : */ 121 588 : int result = score1 + score2; 122 : 123 : // First handle the cases where one or both is infinite 124 588 : if ((score1 <= -PCMK_SCORE_INFINITY) || (score2 <= -PCMK_SCORE_INFINITY)) { 125 79 : return -PCMK_SCORE_INFINITY; 126 : } 127 509 : if ((score1 >= PCMK_SCORE_INFINITY) || (score2 >= PCMK_SCORE_INFINITY)) { 128 10 : return PCMK_SCORE_INFINITY; 129 : } 130 : 131 : // Bound result to infinity. 132 499 : if (result >= PCMK_SCORE_INFINITY) { 133 1 : return PCMK_SCORE_INFINITY; 134 : } 135 498 : if (result <= -PCMK_SCORE_INFINITY) { 136 1 : return -PCMK_SCORE_INFINITY; 137 : } 138 : 139 497 : return result; 140 : } 141 : 142 : // Deprecated functions kept only for backward API compatibility 143 : // LCOV_EXCL_START 144 : 145 : #include <crm/common/scores_compat.h> 146 : 147 : char * 148 : score2char(int score) 149 : { 150 : return pcmk__str_copy(pcmk_readable_score(score)); 151 : } 152 : 153 : char * 154 : score2char_stack(int score, char *buf, size_t len) 155 : { 156 : CRM_CHECK((buf != NULL) && (len >= sizeof(PCMK_VALUE_MINUS_INFINITY)), 157 : return NULL); 158 : strcpy(buf, pcmk_readable_score(score)); 159 : return buf; 160 : } 161 : 162 : // LCOV_EXCL_STOP 163 : // End deprecated API