Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / WINNT / license / multistring.cpp
blob4a24facea48e0c78587759e8b9c88cd594c2a3e7
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
10 #include <windows.h>
11 #include "multistring.h"
14 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
16 if (!pszA || !pszB)
18 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
21 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
23 TCHAR chA = toupper( *pszA );
24 TCHAR chB = toupper( *pszB );
26 if (!chA || !chB)
27 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
29 if (chA != chB)
30 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
33 return 0; // no differences before told to stop comparing, so A==B
38 * mstralloc - Allocates space for a given-length multistring
39 * mstrfree - Frees a multistring
40 * mstrwalk - Allows iterative progression along a multistring
41 * mstrlen - Returns the length of a given multistring, including all \0's
42 * mstrcount - Returns the number of entries in a given multistring
43 * mstrstr - Determines if a given substring exists in a multistring
44 * mstrcat - Adds a substring to a multistring (doesn't do any checking first)
45 * mstrdel - Removes a substring from a multistring
49 LPTSTR mstralloc (size_t cchMax)
51 LPTSTR msz;
52 if ((msz = (LPTSTR)GlobalAlloc (GMEM_FIXED, sizeof(TCHAR) * (1+cchMax))) != NULL)
53 memset (msz, 0x00, sizeof(TCHAR) * (1+cchMax));
54 return msz;
58 void mstrfree (LPCTSTR msz)
60 if (msz)
61 GlobalFree ((HGLOBAL)msz);
65 BOOL mstrwalk (LPCTSTR msz, TCHAR chSep, LPTSTR *ppSegment, size_t *pchSegment)
67 // If the caller supplied {*ppSegment} as NULL, we should return the
68 // first segment. Otherwise, advance {*pchSegment} characters and
69 // return the next segment.
71 if (!*ppSegment)
72 *ppSegment = (LPTSTR)msz;
73 else if (*(*ppSegment += *pchSegment) == chSep)
74 (*ppSegment) ++;
75 else
76 return FALSE;
78 if (!*ppSegment || !*(*ppSegment))
79 return FALSE;
81 *pchSegment = 0;
82 while ((*ppSegment)[*pchSegment] && ((*ppSegment)[*pchSegment] != chSep))
83 (*pchSegment)++;
85 return TRUE;
89 size_t mstrlen (LPCTSTR msz, TCHAR chSep)
91 LPTSTR pSegment = NULL;
92 size_t cchSegment = 0;
94 size_t cchTotal = 0;
95 while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
96 cchTotal += cchSegment+1;
98 if (!chSep || !cchTotal)
99 cchTotal ++; // To terminate the string
101 return cchTotal;
105 size_t mstrcount (LPCTSTR msz, TCHAR chSep)
107 LPTSTR pSegment = NULL;
108 size_t cchSegment = 0;
110 size_t cSegments = 0;
111 while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
112 cSegments ++;
114 return cSegments;
118 BOOL mstrstr (LPCTSTR msz, TCHAR chSep, LPCTSTR pszTest)
120 LPTSTR pSegment = NULL;
121 size_t cchSegment = 0;
123 size_t cchTotal = 0;
124 while (mstrwalk (msz, chSep, &pSegment, &cchSegment))
126 if ( (cchSegment == (size_t)lstrlen(pszTest)) &&
127 (!lstrncmpi (pSegment, pszTest, cchSegment)) )
128 return TRUE;
131 return FALSE;
135 BOOL mstrcat (LPTSTR *pmsz, TCHAR chSep, LPCTSTR pszAppend)
137 size_t cchOld = mstrlen(*pmsz,chSep);
138 size_t cchAdd = (pszAppend) ? lstrlen(pszAppend) : 0;
139 size_t cchRetain = (chSep && (cchOld!=1)) ? cchOld : (cchOld-1);
141 LPTSTR mszNew;
142 if ((mszNew = mstralloc (cchRetain + cchAdd + 2)) == NULL)
143 return FALSE;
145 if (cchRetain)
146 memcpy (mszNew, *pmsz, sizeof(TCHAR) * cchRetain);
148 if (cchRetain)
149 mszNew[ cchRetain-1 ] = chSep;
151 lstrcpy (&mszNew[ cchRetain ], pszAppend);
153 if (!chSep)
154 mszNew[ cchRetain + cchAdd +1 ] = 0;
156 if (*pmsz)
157 mstrfree (*pmsz);
158 *pmsz = mszNew;
159 return TRUE;
163 BOOL mstrdel (LPTSTR *pmsz, TCHAR chSep, LPCTSTR pszRemove)
165 LPTSTR mszNew;
166 if ((mszNew = mstralloc (mstrlen(*pmsz,chSep))) == NULL)
167 return FALSE;
169 LPTSTR pSegmentWrite = mszNew;
170 LPTSTR pSegmentRead = NULL;
171 size_t cchSegment = 0;
173 size_t cchTotal = 0;
174 while (mstrwalk (*pmsz, chSep, &pSegmentRead, &cchSegment))
176 if ( (cchSegment == (size_t)lstrlen(pszRemove)) &&
177 (!lstrncmpi (pSegmentRead, pszRemove, cchSegment)) )
178 continue;
180 for (size_t ich = 0; ich < cchSegment; ++ich)
181 *pSegmentWrite++ = pSegmentRead[ ich ];
182 *pSegmentWrite++ = chSep;
184 if ((pSegmentWrite != mszNew) && (chSep)) // don't need trailing separator
185 pSegmentWrite--;
186 *pSegmentWrite = 0;
188 if (*pmsz)
189 mstrfree (*pmsz);
190 *pmsz = mszNew;
191 return TRUE;