Home | History | Annotate | Line # | Download | only in libopts
      1  1.7  christos /*	$NetBSD: streqvcmp.c,v 1.8 2024/08/18 20:47:25 christos Exp $	*/
      2  1.1    kardel 
      3  1.1    kardel 
      4  1.2  christos /**
      5  1.2  christos  * \file streqvcmp.c
      6  1.2  christos  *
      7  1.1    kardel  *  String Equivalence Comparison
      8  1.1    kardel  *
      9  1.1    kardel  *  These routines allow any character to be mapped to any other
     10  1.1    kardel  *  character before comparison.  In processing long option names,
     11  1.1    kardel  *  the characters "-", "_" and "^" all need to be equivalent
     12  1.1    kardel  *  (because they are treated so by different development environments).
     13  1.1    kardel  *
     14  1.3  christos  * @addtogroup autoopts
     15  1.3  christos  * @{
     16  1.3  christos  */
     17  1.3  christos /*
     18  1.1    kardel  *  This file is part of AutoOpts, a companion to AutoGen.
     19  1.1    kardel  *  AutoOpts is free software.
     20  1.8  christos  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
     21  1.1    kardel  *
     22  1.1    kardel  *  AutoOpts is available under any one of two licenses.  The license
     23  1.1    kardel  *  in use must be one of these two and the choice is under the control
     24  1.1    kardel  *  of the user of the license.
     25  1.1    kardel  *
     26  1.1    kardel  *   The GNU Lesser General Public License, version 3 or later
     27  1.1    kardel  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
     28  1.1    kardel  *
     29  1.1    kardel  *   The Modified Berkeley Software Distribution License
     30  1.1    kardel  *      See the file "COPYING.mbsd"
     31  1.1    kardel  *
     32  1.3  christos  *  These files have the following sha256 sums:
     33  1.1    kardel  *
     34  1.3  christos  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
     35  1.3  christos  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
     36  1.3  christos  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
     37  1.1    kardel  *
     38  1.1    kardel  * This array is designed for mapping upper and lower case letter
     39  1.1    kardel  * together for a case independent comparison.  The mappings are
     40  1.1    kardel  * based upon ascii character sequences.
     41  1.1    kardel  */
     42  1.8  christos   static unsigned char charmap[] = {
     43  1.3  christos     NUL,  0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
     44  1.3  christos     '\b', '\t', NL,   '\v',  '\f', '\r', 0x0E, 0x0F,
     45  1.1    kardel     0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
     46  1.1    kardel     0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
     47  1.1    kardel 
     48  1.1    kardel     ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
     49  1.1    kardel     '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
     50  1.1    kardel     '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
     51  1.1    kardel     '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
     52  1.1    kardel 
     53  1.1    kardel     '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
     54  1.1    kardel     'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
     55  1.1    kardel     'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
     56  1.1    kardel     'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
     57  1.1    kardel     '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
     58  1.1    kardel     'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
     59  1.1    kardel     'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
     60  1.1    kardel     'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
     61  1.1    kardel 
     62  1.1    kardel     0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
     63  1.1    kardel     0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
     64  1.1    kardel     0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
     65  1.1    kardel     0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
     66  1.1    kardel     0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
     67  1.1    kardel     0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
     68  1.1    kardel     0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
     69  1.1    kardel     0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
     70  1.1    kardel 
     71  1.1    kardel     0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
     72  1.1    kardel     0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
     73  1.1    kardel     0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
     74  1.1    kardel     0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
     75  1.1    kardel     0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
     76  1.1    kardel     0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
     77  1.1    kardel     0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
     78  1.1    kardel     0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
     79  1.1    kardel };
     80  1.1    kardel 
     81  1.1    kardel 
     82  1.1    kardel /*=export_func strneqvcmp
     83  1.1    kardel  *
     84  1.1    kardel  * what: compare two strings with an equivalence mapping
     85  1.1    kardel  *
     86  1.5  christos  * arg:  + char const * + str1 + first string +
     87  1.5  christos  * arg:  + char const * + str2 + second string +
     88  1.5  christos  * arg:  + int          + ct   + compare length +
     89  1.1    kardel  *
     90  1.1    kardel  * ret_type:  int
     91  1.1    kardel  * ret_desc:  the difference between two differing characters
     92  1.1    kardel  *
     93  1.1    kardel  * doc:
     94  1.1    kardel  *
     95  1.1    kardel  * Using a character mapping, two strings are compared for "equivalence".
     96  1.1    kardel  * Each input character is mapped to a comparison character and the
     97  1.1    kardel  * mapped-to characters are compared for the two NUL terminated input strings.
     98  1.1    kardel  * The comparison is limited to @code{ct} bytes.
     99  1.1    kardel  * This function name is mapped to option_strneqvcmp so as to not conflict
    100  1.1    kardel  * with the POSIX name space.
    101  1.1    kardel  *
    102  1.1    kardel  * err:  none checked.  Caller responsible for seg faults.
    103  1.1    kardel =*/
    104  1.1    kardel int
    105  1.3  christos strneqvcmp(char const * s1, char const * s2, int ct)
    106  1.1    kardel {
    107  1.1    kardel     for (; ct > 0; --ct) {
    108  1.1    kardel         unsigned char u1 = (unsigned char) *s1++;
    109  1.1    kardel         unsigned char u2 = (unsigned char) *s2++;
    110  1.3  christos         int dif;
    111  1.3  christos         if (u1 == u2) {
    112  1.3  christos             if (u1 == NUL)
    113  1.3  christos                 return 0;
    114  1.3  christos             continue;
    115  1.3  christos         }
    116  1.3  christos 
    117  1.3  christos         dif = charmap[ u1 ] - charmap[ u2 ];
    118  1.1    kardel 
    119  1.1    kardel         if (dif != 0)
    120  1.1    kardel             return dif;
    121  1.1    kardel 
    122  1.1    kardel         if (u1 == NUL)
    123  1.1    kardel             return 0;
    124  1.1    kardel     }
    125  1.1    kardel 
    126  1.1    kardel     return 0;
    127  1.1    kardel }
    128  1.1    kardel 
    129  1.1    kardel 
    130  1.1    kardel /*=export_func streqvcmp
    131  1.1    kardel  *
    132  1.1    kardel  * what: compare two strings with an equivalence mapping
    133  1.1    kardel  *
    134  1.5  christos  * arg:  + char const * + str1 + first string +
    135  1.5  christos  * arg:  + char const * + str2 + second string +
    136  1.1    kardel  *
    137  1.1    kardel  * ret_type:  int
    138  1.1    kardel  * ret_desc:  the difference between two differing characters
    139  1.1    kardel  *
    140  1.1    kardel  * doc:
    141  1.1    kardel  *
    142  1.1    kardel  * Using a character mapping, two strings are compared for "equivalence".
    143  1.1    kardel  * Each input character is mapped to a comparison character and the
    144  1.1    kardel  * mapped-to characters are compared for the two NUL terminated input strings.
    145  1.1    kardel  * This function name is mapped to option_streqvcmp so as to not conflict
    146  1.1    kardel  * with the POSIX name space.
    147  1.1    kardel  *
    148  1.1    kardel  * err:  none checked.  Caller responsible for seg faults.
    149  1.1    kardel =*/
    150  1.1    kardel int
    151  1.3  christos streqvcmp(char const * s1, char const * s2)
    152  1.1    kardel {
    153  1.1    kardel     for (;;) {
    154  1.1    kardel         unsigned char u1 = (unsigned char) *s1++;
    155  1.1    kardel         unsigned char u2 = (unsigned char) *s2++;
    156  1.3  christos         int dif;
    157  1.3  christos         if (u1 == u2) {
    158  1.3  christos             if (u1 == NUL)
    159  1.3  christos                 return 0;
    160  1.3  christos             continue;
    161  1.3  christos         }
    162  1.3  christos 
    163  1.3  christos         dif = charmap[ u1 ] - charmap[ u2 ];
    164  1.1    kardel 
    165  1.1    kardel         if (dif != 0)
    166  1.1    kardel             return dif;
    167  1.1    kardel 
    168  1.1    kardel         if (u1 == NUL)
    169  1.1    kardel             return 0;
    170  1.1    kardel     }
    171  1.1    kardel }
    172  1.1    kardel 
    173  1.1    kardel 
    174  1.1    kardel /*=export_func streqvmap
    175  1.1    kardel  *
    176  1.1    kardel  * what: Set the character mappings for the streqv functions
    177  1.1    kardel  *
    178  1.3  christos  * arg:  + char + from + Input character +
    179  1.3  christos  * arg:  + char + to   + Mapped-to character +
    180  1.1    kardel  * arg:  + int  + ct   + compare length +
    181  1.1    kardel  *
    182  1.1    kardel  * doc:
    183  1.1    kardel  *
    184  1.1    kardel  * Set the character mapping.  If the count (@code{ct}) is set to zero, then
    185  1.1    kardel  * the map is cleared by setting all entries in the map to their index
    186  1.1    kardel  * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
    187  1.1    kardel  * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
    188  1.1    kardel  * are incremented and the process repeated until @code{ct} entries have been
    189  1.1    kardel  * set. For example,
    190  1.1    kardel  * @example
    191  1.2  christos  *    streqvmap('a', 'A', 26);
    192  1.1    kardel  * @end example
    193  1.1    kardel  * @noindent
    194  1.1    kardel  * will alter the mapping so that all English lower case letters
    195  1.1    kardel  * will map to upper case.
    196  1.1    kardel  *
    197  1.1    kardel  * This function name is mapped to option_streqvmap so as to not conflict
    198  1.1    kardel  * with the POSIX name space.
    199  1.1    kardel  *
    200  1.1    kardel  * err:  none.
    201  1.1    kardel =*/
    202  1.1    kardel void
    203  1.3  christos streqvmap(char from, char to, int ct)
    204  1.1    kardel {
    205  1.1    kardel     if (ct == 0) {
    206  1.2  christos         ct = sizeof(charmap) - 1;
    207  1.1    kardel         do  {
    208  1.3  christos             charmap[ct] = (unsigned char)ct;
    209  1.1    kardel         } while (--ct >= 0);
    210  1.1    kardel     }
    211  1.1    kardel 
    212  1.1    kardel     else {
    213  1.3  christos         unsigned int i_to   = (int)to   & 0xFF;
    214  1.3  christos         unsigned int i_from = (int)from & 0xFF;
    215  1.1    kardel 
    216  1.1    kardel         do  {
    217  1.3  christos             charmap[i_from] = (unsigned char)i_to;
    218  1.3  christos             i_from++;
    219  1.3  christos             i_to++;
    220  1.3  christos             if ((i_from >= sizeof(charmap)) || (i_to >= sizeof(charmap)))
    221  1.1    kardel                 break;
    222  1.1    kardel         } while (--ct > 0);
    223  1.1    kardel     }
    224  1.1    kardel }
    225  1.1    kardel 
    226  1.1    kardel 
    227  1.1    kardel /*=export_func strequate
    228  1.1    kardel  *
    229  1.1    kardel  * what: map a list of characters to the same value
    230  1.1    kardel  *
    231  1.5  christos  * arg:  + char const * + ch_list + characters to equivalence +
    232  1.1    kardel  *
    233  1.1    kardel  * doc:
    234  1.1    kardel  *
    235  1.1    kardel  * Each character in the input string get mapped to the first character
    236  1.1    kardel  * in the string.
    237  1.1    kardel  * This function name is mapped to option_strequate so as to not conflict
    238  1.1    kardel  * with the POSIX name space.
    239  1.1    kardel  *
    240  1.1    kardel  * err:  none.
    241  1.1    kardel =*/
    242  1.1    kardel void
    243  1.5  christos strequate(char const * s)
    244  1.1    kardel {
    245  1.1    kardel     if ((s != NULL) && (*s != NUL)) {
    246  1.3  christos         unsigned char equiv = (unsigned char)*s;
    247  1.1    kardel         while (*s != NUL)
    248  1.3  christos             charmap[(unsigned char)*(s++)] = equiv;
    249  1.1    kardel     }
    250  1.1    kardel }
    251  1.1    kardel 
    252  1.1    kardel 
    253  1.1    kardel /*=export_func strtransform
    254  1.1    kardel  *
    255  1.1    kardel  * what: convert a string into its mapped-to value
    256  1.1    kardel  *
    257  1.5  christos  * arg:  + char *       + dest + output string +
    258  1.5  christos  * arg:  + char const * + src  + input string +
    259  1.1    kardel  *
    260  1.1    kardel  * doc:
    261  1.1    kardel  *
    262  1.1    kardel  * Each character in the input string is mapped and the mapped-to
    263  1.1    kardel  * character is put into the output.
    264  1.1    kardel  * This function name is mapped to option_strtransform so as to not conflict
    265  1.1    kardel  * with the POSIX name space.
    266  1.1    kardel  *
    267  1.1    kardel  * The source and destination may be the same.
    268  1.1    kardel  *
    269  1.1    kardel  * err:  none.
    270  1.1    kardel =*/
    271  1.1    kardel void
    272  1.5  christos strtransform(char * d, char const * s)
    273  1.1    kardel {
    274  1.1    kardel     do  {
    275  1.3  christos         *(d++) = (char)charmap[(unsigned char)*s];
    276  1.1    kardel     } while (*(s++) != NUL);
    277  1.1    kardel }
    278  1.1    kardel 
    279  1.3  christos /** @}
    280  1.3  christos  *
    281  1.1    kardel  * Local Variables:
    282  1.1    kardel  * mode: C
    283  1.1    kardel  * c-file-style: "stroustrup"
    284  1.1    kardel  * indent-tabs-mode: nil
    285  1.1    kardel  * End:
    286  1.1    kardel  * end of autoopts/streqvcmp.c */
    287