1784088dfSchristos /*
2784088dfSchristos * Copyright (c) 1987 Regents of the University of California.
3784088dfSchristos * All rights reserved.
4784088dfSchristos *
5784088dfSchristos * Redistribution and use in source and binary forms are permitted
6784088dfSchristos * provided that this notice is preserved and that due credit is given
7784088dfSchristos * to the University of California at Berkeley. The name of the University
8784088dfSchristos * may not be used to endorse or promote products derived from this
9784088dfSchristos * software without specific written prior permission. This software
10784088dfSchristos * is provided ``as is'' without express or implied warranty.
11784088dfSchristos */
12784088dfSchristos
13fdccd7e4Schristos #include <sys/cdefs.h>
14fdccd7e4Schristos #ifndef lint
15*c74ad251Schristos __RCSID("$NetBSD: ascii_strcasecmp.c,v 1.3 2023/08/17 20:19:39 christos Exp $");
16fdccd7e4Schristos #endif
17fdccd7e4Schristos
18784088dfSchristos #include "ascii_strcasecmp.h"
19784088dfSchristos
20784088dfSchristos /*
21784088dfSchristos * This array maps upper-case ASCII letters to their lower-case
22784088dfSchristos * equivalents; all other byte values are mapped to themselves,
23784088dfSchristos * so this is locale-independent and intended to be locale-independent,
24784088dfSchristos * to avoid issues with, for example, "i" and "I" not being lower-case
25784088dfSchristos * and upper-case versions of the same letter in Turkish, where
26784088dfSchristos * there are separate "i with dot" and "i without dot" letters.
27784088dfSchristos */
28784088dfSchristos static const unsigned char charmap[] = {
29784088dfSchristos 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
30784088dfSchristos 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
31784088dfSchristos 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
32784088dfSchristos 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
33784088dfSchristos 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
34784088dfSchristos 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
35784088dfSchristos 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
36784088dfSchristos 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
37784088dfSchristos 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
38784088dfSchristos 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
39784088dfSchristos 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
40784088dfSchristos 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
41784088dfSchristos 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
42784088dfSchristos 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
43784088dfSchristos 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
44784088dfSchristos 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
45784088dfSchristos 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
46784088dfSchristos 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
47784088dfSchristos 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
48784088dfSchristos 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
49784088dfSchristos 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
50784088dfSchristos 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
51784088dfSchristos 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
52784088dfSchristos 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
53784088dfSchristos 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
54784088dfSchristos 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
55784088dfSchristos 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
56784088dfSchristos 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
57784088dfSchristos 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
58784088dfSchristos 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
59784088dfSchristos 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
60784088dfSchristos 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
61784088dfSchristos };
62784088dfSchristos
63784088dfSchristos int
ascii_strcasecmp(const char * s1,const char * s2)64784088dfSchristos ascii_strcasecmp(const char *s1, const char *s2)
65784088dfSchristos {
66*c74ad251Schristos const unsigned char *cm = charmap,
67784088dfSchristos *us1 = (const unsigned char *)s1,
68784088dfSchristos *us2 = (const unsigned char *)s2;
69784088dfSchristos
70784088dfSchristos while (cm[*us1] == cm[*us2++])
71784088dfSchristos if (*us1++ == '\0')
72784088dfSchristos return(0);
73784088dfSchristos return(cm[*us1] - cm[*--us2]);
74784088dfSchristos }
75784088dfSchristos
76784088dfSchristos int
ascii_strncasecmp(const char * s1,const char * s2,size_t n)77*c74ad251Schristos ascii_strncasecmp(const char *s1, const char *s2, size_t n)
78784088dfSchristos {
79*c74ad251Schristos const unsigned char *cm = charmap,
80784088dfSchristos *us1 = (const unsigned char *)s1,
81784088dfSchristos *us2 = (const unsigned char *)s2;
82784088dfSchristos
83784088dfSchristos for (;;) {
84784088dfSchristos if (n == 0) {
85784088dfSchristos /*
86784088dfSchristos * We've run out of characters that we should
87784088dfSchristos * compare, and they've all been equal; return
88784088dfSchristos * 0, to indicate that the prefixes are the
89784088dfSchristos * same.
90784088dfSchristos */
91784088dfSchristos return(0);
92784088dfSchristos }
93784088dfSchristos if (cm[*us1] != cm[*us2++]) {
94784088dfSchristos /*
95784088dfSchristos * We've found a mismatch.
96784088dfSchristos */
97784088dfSchristos break;
98784088dfSchristos }
99784088dfSchristos if (*us1++ == '\0') {
100784088dfSchristos /*
101784088dfSchristos * We've run out of characters *to* compare,
102784088dfSchristos * and they've all been equal; return 0, to
103784088dfSchristos * indicate that the strings are the same.
104784088dfSchristos */
105784088dfSchristos return(0);
106784088dfSchristos }
107784088dfSchristos n--;
108784088dfSchristos }
109784088dfSchristos return(cm[*us1] - cm[*--us2]);
110784088dfSchristos }
111