Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / WINNT / license / multistring.cpp
1 #include <windows.h>
2 #include "multistring.h"
3
4
5 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
6 {
7    if (!pszA || !pszB)
8       {
9       return (!pszB) - (!pszA);   // A,!B:1, !A,B:-1, !A,!B:0
10       }
11
12    for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
13       {
14       TCHAR chA = toupper( *pszA );
15       TCHAR chB = toupper( *pszB );
16
17       if (!chA || !chB)
18          return (!chB) - (!chA);    // A,!B:1, !A,B:-1, !A,!B:0
19
20       if (chA != chB)
21          return (int)(chA) - (int)(chB);   // -1:A<B, 0:A==B, 1:A>B
22       }
23
24    return 0;  // no differences before told to stop comparing, so A==B
25 }
26
27
28 /*
29  * mstralloc - Allocates space for a given-length multistring
30  * mstrfree - Frees a multistring
31  * mstrwalk - Allows iterative progression along a multistring
32  * mstrlen - Returns the length of a given multistring, including all \0's
33  * mstrcount - Returns the number of entries in a given multistring
34  * mstrstr - Determines if a given substring exists in a multistring
35  * mstrcat - Adds a substring to a multistring (doesn't do any checking first)
36  * mstrdel - Removes a substring from a multistring
37  *
38  */
39
40 LPTSTR mstralloc (size_t cchMax)
41 {
42    LPTSTR msz;
43    if ((msz = (LPTSTR)GlobalAlloc (GMEM_FIXED, sizeof(TCHAR) * (1+cchMax))) != NULL)
44       memset (msz, 0x00, sizeof(TCHAR) * (1+cchMax));
45    return msz;
46 }
47
48
49 void mstrfree (LPCTSTR msz)
50 {
51    if (msz)
52       GlobalFree ((HGLOBAL)msz);
53 }
54
55
56 BOOL mstrwalk (LPCTSTR msz, TCHAR chSep, LPTSTR *ppSegment, size_t *pchSegment)
57 {
58    // If the caller supplied {*ppSegment} as NULL, we should return the
59    // first segment. Otherwise, advance {*pchSegment} characters and
60    // return the next segment.
61    //
62    if (!*ppSegment)
63       *ppSegment = (LPTSTR)msz;
64    else if (*(*ppSegment += *pchSegment) == chSep)
65       (*ppSegment) ++;
66    else
67       return FALSE;
68
69    if (!*ppSegment || !*(*ppSegment))
70       return FALSE;
71
72    *pchSegment = 0;
73    while ((*ppSegment)[*pchSegment] && ((*ppSegment)[*pchSegment] != chSep))
74       (*pchSegment)++;
75
76    return TRUE;
77 }
78
79
80 size_t mstrlen (LPCTSTR msz, TCHAR chSep)
81 {
82    LPTSTR pSegment = NULL;
83    size_t cchSegment = 0;
84
85    size_t cchTotal = 0;
86    while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
87       cchTotal += cchSegment+1;
88
89    if (!chSep || !cchTotal)
90       cchTotal ++;     // To terminate the string
91
92    return cchTotal;
93 }
94
95
96 size_t mstrcount (LPCTSTR msz, TCHAR chSep)
97 {
98    LPTSTR pSegment = NULL;
99    size_t cchSegment = 0;
100
101    size_t cSegments = 0;
102    while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
103       cSegments ++;
104
105    return cSegments;
106 }
107
108
109 BOOL mstrstr (LPCTSTR msz, TCHAR chSep, LPCTSTR pszTest)
110 {
111    LPTSTR pSegment = NULL;
112    size_t cchSegment = 0;
113
114    size_t cchTotal = 0;
115    while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
116       {
117       if ( (cchSegment == (size_t)lstrlen(pszTest)) &&
118            (!lstrncmpi (pSegment, pszTest, cchSegment)) )
119          return TRUE;
120       }
121
122    return FALSE;
123 }
124
125
126 BOOL mstrcat (LPTSTR *pmsz, TCHAR chSep, LPCTSTR pszAppend)
127 {
128    size_t cchOld = mstrlen(*pmsz,chSep);
129    size_t cchAdd = (pszAppend) ? lstrlen(pszAppend) : 0;
130    size_t cchRetain = (chSep && (cchOld!=1)) ? cchOld : (cchOld-1);
131
132    LPTSTR mszNew;
133    if ((mszNew = mstralloc (cchRetain + cchAdd + 2)) == NULL)
134       return FALSE;
135
136    if (cchRetain)
137       memcpy (mszNew, *pmsz, sizeof(TCHAR) * cchRetain);
138
139    if (cchRetain)
140       mszNew[ cchRetain-1 ] = chSep;
141
142    lstrcpy (&mszNew[ cchRetain ], pszAppend);
143
144    if (!chSep)
145       mszNew[ cchRetain + cchAdd +1 ] = 0;
146
147    if (*pmsz)
148       mstrfree (*pmsz);
149    *pmsz = mszNew;
150    return TRUE;
151 }
152
153
154 BOOL mstrdel (LPTSTR *pmsz, TCHAR chSep, LPCTSTR pszRemove)
155 {
156    LPTSTR mszNew;
157    if ((mszNew = mstralloc (mstrlen(*pmsz,chSep))) == NULL)
158       return FALSE;
159
160    LPTSTR pSegmentWrite = mszNew;
161    LPTSTR pSegmentRead = NULL;
162    size_t cchSegment = 0;
163
164    size_t cchTotal = 0;
165    while (mstrwalk (*pmsz, chSep, &pSegmentRead, &cchSegment))
166       {
167       if ( (cchSegment == (size_t)lstrlen(pszRemove)) &&
168            (!lstrncmpi (pSegmentRead, pszRemove, cchSegment)) )
169          continue;
170
171       for (size_t ich = 0; ich < cchSegment; ++ich)
172          *pSegmentWrite++ = pSegmentRead[ ich ];
173       *pSegmentWrite++ = chSep;
174       }
175    if ((pSegmentWrite != mszNew) && (chSep)) // don't need trailing separator
176       pSegmentWrite--;
177    *pSegmentWrite = 0;
178
179    if (*pmsz)
180       mstrfree (*pmsz);
181    *pmsz = mszNew;
182    return TRUE;
183 }
184