2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include "multistring.h"
14 static int lstrncmpi (LPCTSTR pszA
, LPCTSTR pszB
, size_t cch
)
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
);
27 return (!chB
) - (!chA
); // A,!B:1, !A,B:-1, !A,!B:0
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
)
52 if ((msz
= (LPTSTR
)GlobalAlloc (GMEM_FIXED
, sizeof(TCHAR
) * (1+cchMax
))) != NULL
)
53 memset (msz
, 0x00, sizeof(TCHAR
) * (1+cchMax
));
58 void mstrfree (LPCTSTR 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.
72 *ppSegment
= (LPTSTR
)msz
;
73 else if (*(*ppSegment
+= *pchSegment
) == chSep
)
78 if (!*ppSegment
|| !*(*ppSegment
))
82 while ((*ppSegment
)[*pchSegment
] && ((*ppSegment
)[*pchSegment
] != chSep
))
89 size_t mstrlen (LPCTSTR msz
, TCHAR chSep
)
91 LPTSTR pSegment
= NULL
;
92 size_t cchSegment
= 0;
95 while (mstrwalk (msz
, chSep
, &pSegment
, &cchSegment
))
96 cchTotal
+= cchSegment
+1;
98 if (!chSep
|| !cchTotal
)
99 cchTotal
++; // To terminate the string
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
))
118 BOOL
mstrstr (LPCTSTR msz
, TCHAR chSep
, LPCTSTR pszTest
)
120 LPTSTR pSegment
= NULL
;
121 size_t cchSegment
= 0;
124 while (mstrwalk (msz
, chSep
, &pSegment
, &cchSegment
))
126 if ( (cchSegment
== (size_t)lstrlen(pszTest
)) &&
127 (!lstrncmpi (pSegment
, pszTest
, cchSegment
)) )
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);
142 if ((mszNew
= mstralloc (cchRetain
+ cchAdd
+ 2)) == NULL
)
146 memcpy (mszNew
, *pmsz
, sizeof(TCHAR
) * cchRetain
);
149 mszNew
[ cchRetain
-1 ] = chSep
;
151 lstrcpy (&mszNew
[ cchRetain
], pszAppend
);
154 mszNew
[ cchRetain
+ cchAdd
+1 ] = 0;
163 BOOL
mstrdel (LPTSTR
*pmsz
, TCHAR chSep
, LPCTSTR pszRemove
)
166 if ((mszNew
= mstralloc (mstrlen(*pmsz
,chSep
))) == NULL
)
169 LPTSTR pSegmentWrite
= mszNew
;
170 LPTSTR pSegmentRead
= NULL
;
171 size_t cchSegment
= 0;
174 while (mstrwalk (*pmsz
, chSep
, &pSegmentRead
, &cchSegment
))
176 if ( (cchSegment
== (size_t)lstrlen(pszRemove
)) &&
177 (!lstrncmpi (pSegmentRead
, pszRemove
, cchSegment
)) )
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