busybox/libbb/compare_string_array.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   4 */
   5#include "libbb.h"
   6
   7/*
   8 * Return NULL if string is not prefixed with key. Return pointer to the
   9 * first character in string after the prefix key. If key is an empty string,
  10 * return pointer to the beginning of string.
  11 */
  12char* FAST_FUNC is_prefixed_with(const char *string, const char *key)
  13{
  14#if 0   /* Two passes over key - probably slower */
  15        int len = strlen(key);
  16        if (strncmp(string, key, len) == 0)
  17                return string + len;
  18        return NULL;
  19#else   /* Open-coded */
  20        while (*key != '\0') {
  21                if (*key != *string)
  22                        return NULL;
  23                key++;
  24                string++;
  25        }
  26        return (char*)string;
  27#endif
  28}
  29
  30/*
  31 * Return NULL if string is not suffixed with key. Return pointer to the
  32 * beginning of prefix key in string. If key is an empty string return pointer
  33 * to the end of string.
  34 */
  35char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
  36{
  37        size_t key_len = strlen(key);
  38        ssize_t len_diff = strlen(string) - key_len;
  39
  40        if (len_diff >= 0) {
  41                string += len_diff;
  42                if (strcmp(string, key) == 0) {
  43                        return (char*)string;
  44                }
  45        }
  46
  47        return NULL;
  48}
  49
  50/* returns the array index of the string */
  51/* (index of first match is returned, or -1) */
  52int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key)
  53{
  54        int i;
  55
  56        for (i = 0; string_array[i] != 0; i++) {
  57                if (strcmp(string_array[i], key) == 0) {
  58                        return i;
  59                }
  60        }
  61        return -1;
  62}
  63
  64int FAST_FUNC index_in_strings(const char *strings, const char *key)
  65{
  66        int j, idx = 0;
  67
  68        while (*strings) {
  69                /* Do we see "key\0" at current position in strings? */
  70                for (j = 0; *strings == key[j]; ++j) {
  71                        if (*strings++ == '\0') {
  72                                //bb_error_msg("found:'%s' i:%u", key, idx);
  73                                return idx; /* yes */
  74                        }
  75                }
  76                /* No.  Move to the start of the next string. */
  77                while (*strings++ != '\0')
  78                        continue;
  79                idx++;
  80        }
  81        return -1;
  82}
  83
  84/* returns the array index of the string, even if it matches only a beginning */
  85/* (index of first match is returned, or -1) */
  86#ifdef UNUSED
  87int FAST_FUNC index_in_substr_array(const char *const string_array[], const char *key)
  88{
  89        int i;
  90        if (key[0]) {
  91                for (i = 0; string_array[i] != 0; i++) {
  92                        if (is_prefixed_with(string_array[i], key)) {
  93                                return i;
  94                        }
  95                }
  96        }
  97        return -1;
  98}
  99#endif
 100
 101int FAST_FUNC index_in_substrings(const char *strings, const char *key)
 102{
 103        int matched_idx = -1;
 104        const int len = strlen(key);
 105
 106        if (len) {
 107                int idx = 0;
 108                while (*strings) {
 109                        if (strncmp(strings, key, len) == 0) {
 110                                if (strings[len] == '\0')
 111                                        return idx; /* exact match */
 112                                if (matched_idx >= 0)
 113                                        return -1; /* ambiguous match */
 114                                matched_idx = idx;
 115                        }
 116                        strings += strlen(strings) + 1; /* skip NUL */
 117                        idx++;
 118                }
 119        }
 120        return matched_idx;
 121}
 122
 123const char* FAST_FUNC nth_string(const char *strings, int n)
 124{
 125        while (n) {
 126                if (*strings++ == '\0') {
 127                        if (*strings == '\0') /* reached end of strings */
 128                                break;
 129                        n--;
 130                }
 131        }
 132        return strings;
 133}
 134
 135#ifdef UNUSED_SO_FAR /* only brctl.c needs it yet */
 136/* Returns 0 for no, 1 for yes or a negative value on error.  */
 137smallint FAST_FUNC yesno(const char *str)
 138{
 139        static const char no_yes[] ALIGN1 =
 140                "0\0" "off\0" "no\0"
 141                "1\0" "on\0" "yes\0";
 142        int ret = index_in_substrings(no_yes, str);
 143        return ret / 3;
 144}
 145#endif
 146
 147#if ENABLE_UNIT_TEST
 148
 149BBUNIT_DEFINE_TEST(is_prefixed_with)
 150{
 151        BBUNIT_ASSERT_STREQ(" bar", is_prefixed_with("foo bar", "foo"));
 152        BBUNIT_ASSERT_STREQ("bar", is_prefixed_with("foo bar", "foo "));
 153        BBUNIT_ASSERT_STREQ("", is_prefixed_with("foo", "foo"));
 154        BBUNIT_ASSERT_STREQ("foo", is_prefixed_with("foo", ""));
 155        BBUNIT_ASSERT_STREQ("", is_prefixed_with("", ""));
 156
 157        BBUNIT_ASSERT_NULL(is_prefixed_with("foo", "bar foo"));
 158        BBUNIT_ASSERT_NULL(is_prefixed_with("foo foo", "bar"));
 159        BBUNIT_ASSERT_NULL(is_prefixed_with("", "foo"));
 160
 161        BBUNIT_ENDTEST;
 162}
 163
 164BBUNIT_DEFINE_TEST(is_suffixed_with)
 165{
 166        BBUNIT_ASSERT_STREQ("bar", is_suffixed_with("foo bar", "bar"));
 167        BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("foo", "foo"));
 168        BBUNIT_ASSERT_STREQ("", is_suffixed_with("foo", ""));
 169        BBUNIT_ASSERT_STREQ("", is_suffixed_with("", ""));
 170        BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("barfoofoo", "foo"));
 171
 172        BBUNIT_ASSERT_NULL(is_suffixed_with("foo", "bar foo"));
 173        BBUNIT_ASSERT_NULL(is_suffixed_with("foo foo", "bar"));
 174        BBUNIT_ASSERT_NULL(is_suffixed_with("", "foo"));
 175
 176        BBUNIT_ENDTEST;
 177}
 178
 179#endif /* ENABLE_UNIT_TEST */
 180