diff --git a/common/string_calls.c b/common/string_calls.c index 7a0a4817..20e28959 100644 --- a/common/string_calls.c +++ b/common/string_calls.c @@ -1057,3 +1057,88 @@ g_str_to_bitmask(const char *str, const struct bitmask_string bitdefs[], return mask; } +/*****************************************************************************/ +int +g_bitmask_to_charstr(int bitmask, const struct bitmask_char bitdefs[], + char *buff, int bufflen, int *rest) +{ + int rlen = 0; /* Returned length */ + + if (bufflen <= 0) /* Caller error */ + { + rlen = -1; + } + else + { + char *p = buff; + /* Find the last writeable character in the buffer */ + const char *last = buff + (bufflen - 1); + + const struct bitmask_char *b; + + for (b = &bitdefs[0] ; b->c != '\0'; ++b) + { + if ((bitmask & b->mask) != 0) + { + if (p < last) + { + *p++ = b->c; + } + ++rlen; + + /* Remove the bit so we don't report it back */ + bitmask &= ~b->mask; + } + } + *p = '\0'; + + if (rest != NULL) + { + *rest = bitmask; + } + } + + return rlen; +} + +/*****************************************************************************/ +int +g_charstr_to_bitmask(const char *str, const struct bitmask_char bitdefs[], + char *unrecognised, int unrecognised_len) +{ + int bitmask = 0; + const char *cp; + int j = 0; + + if (str != NULL && bitdefs != NULL) + { + for (cp = str ; *cp != '\0' ; ++cp) + { + const struct bitmask_char *b; + char c = toupper(*cp); + + for (b = &bitdefs[0] ; b->c != '\0'; ++b) + { + if (toupper(b->c) == c) + { + bitmask |= b->mask; + break; + } + } + if (b->c == '\0') + { + if (unrecognised != NULL && j < (unrecognised_len - 1)) + { + unrecognised[j++] = *cp; + } + } + } + } + + if (unrecognised != NULL && j < unrecognised_len) + { + unrecognised[j] = '\0'; + } + + return bitmask; +} diff --git a/common/string_calls.h b/common/string_calls.h index f2f635f3..29c066e3 100644 --- a/common/string_calls.h +++ b/common/string_calls.h @@ -52,6 +52,21 @@ struct bitmask_string #define BITMASK_STRING_END_OF_LIST { 0, NULL } +/** + * Map a bitmask to a char value + * + * + * This structure is used by g_bitmask_to_charstr() to specify the + * char for each bit in the bitmask + */ +struct bitmask_char +{ + int mask; + char c; +}; + +#define BITMASK_CHAR_END_OF_LIST { 0, '\0' } + /** * Processes a format string for general info * @@ -158,6 +173,9 @@ g_get_display_num_from_display(const char *display_text); /** * Converts a bitmask into a string for output purposes * + * Similar to g_bitmask_to_charstr(), but tokens are strings, separated + * by delimiters. + * * @param bitmask Bitmask to convert * @param bitdefs Definitions for strings for bits * @param delim Delimiter to use between strings @@ -176,8 +194,12 @@ g_bitmask_to_str(int bitmask, const struct bitmask_string bitdefs[], /*** * Converts a string containing a series of tokens to a bitmask. + * + * Similar to g_charstr_to_bitmask(), but tokens are strings, separated + * by delimiters. + * * @param str Input string - * @param bitmask_string Array mapping tokens to bitmask values + * @param bitdefs Array mapping tokens to bitmask values * @param delim Delimiter for tokens in str * @param[out] unrecognised Buffer for any unrecognised tokens * @param unrecognised_len Length of unrecognised including '\0'; @@ -188,6 +210,46 @@ g_str_to_bitmask(const char *str, const struct bitmask_string bitdefs[], const char *delim, char *unrecognised, int unrecognised_len); +/** + * Converts a bitmask into a string for output purposes + * + * Similar to g_bitmask_to_str(), but tokens are individual characters, and + * there are no delimiters. + * + * @param bitmask Bitmask to convert + * @param bitdefs Definitions for strings for bits + * @param buff Output buff + * @param bufflen Length of buff, including terminator '`\0' + * @param[out] rest Any unused bits which weren't covered by bitdefs. + * May be NULL. + * + * @return Total length excluding terminator which would be written, as + * in snprintf(). Can be used to check for overflow + * + * @note Any undefined bits in the bitmask are appended to the output as + * a hexadecimal constant. + */ +int +g_bitmask_to_charstr(int bitmask, const struct bitmask_char bitdefs[], + char *buff, int bufflen, int *rest); + +/*** + * Converts a string containing a series of characters to a bitmask. + * + * Similar to g_str_to_bitmask(), but tokens are individual characters, and + * there are no delimiters. + * + * @param str Input string + * @param bitdefs Array mapping tokens to bitmask values + * @param delim Delimiter for tokens in str + * @param[out] unrecognised Buffer for any unrecognised tokens + * @param unrecognised_len Length of unrecognised including '\0'; + * @return bitmask value for recognised tokens + */ +int +g_charstr_to_bitmask(const char *str, const struct bitmask_char bitdefs[], + char *unrecognised, int unrecognised_len); + int g_strlen(const char *text); char *g_strchr(const char *text, int c); char *g_strrchr(const char *text, int c);