Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/installer-ca/dutil/strutil.cpp

Issue 11521026: initial custom action library, "hello, world" quality (Closed)
Patch Set: Created Sept. 3, 2013, 12:48 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------ -------------------
2 // <copyright file="strutil.cpp" company="Outercurve Foundation">
3 // Copyright (c) 2004, Outercurve Foundation.
4 // This software is released under Microsoft Reciprocal License (MS-RL).
5 // The license and further copyright text can be found in the file
6 // LICENSE.TXT at the root directory of the distribution.
7 // </copyright>
8 //
9 // <summary>
10 // String helper functions.
11 // </summary>
12 //------------------------------------------------------------------------------ -------------------
13
14 #include "../precomp.h"
15
16 #define ARRAY_GROWTH_SIZE 5
17
18 // Forward declarations.
19 static HRESULT StrAllocStringMapInvariant(
20 __deref_out_z LPWSTR* pscz,
21 __in_z LPCWSTR wzSource,
22 __in int cchSource,
23 __in DWORD dwMapFlags
24 );
25
26 /********************************************************************
27 StrAlloc - allocates or reuses dynamic string memory
28
29 NOTE: caller is responsible for freeing ppwz even if function fails
30 ********************************************************************/
31 extern "C" HRESULT DAPI DAPI StrAlloc(
32 __deref_out_ecount_part(cch, 0) LPWSTR* ppwz,
33 __in DWORD_PTR cch
34 )
35 {
36 Assert(ppwz && cch);
37
38 HRESULT hr = S_OK;
39 LPWSTR pwz = NULL;
40
41 if (cch >= MAXDWORD / sizeof(WCHAR))
42 {
43 hr = E_OUTOFMEMORY;
44 ExitOnFailure1(hr, "Not enough memory to allocate string of size: %u", c ch);
45 }
46
47 if (*ppwz)
48 {
49 pwz = static_cast<LPWSTR>(MemReAlloc(*ppwz, sizeof(WCHAR) * cch, FALSE)) ;
50 }
51 else
52 {
53 pwz = static_cast<LPWSTR>(MemAlloc(sizeof(WCHAR) * cch, TRUE));
54 }
55
56 ExitOnNull1(pwz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %u", cc h);
57
58 *ppwz = pwz;
59 LExit:
60 return hr;
61 }
62
63
64 /********************************************************************
65 StrTrimCapacity - Frees any unnecessary memory associated with a string.
66 Purely used for optimization, generally only when a string
67 has been changing size, and will no longer grow.
68
69 NOTE: caller is responsible for freeing ppwz even if function fails
70 ********************************************************************/
71 HRESULT DAPI StrTrimCapacity(
72 __deref_out_z LPWSTR* ppwz
73 )
74 {
75 Assert(ppwz);
76
77 HRESULT hr = S_OK;
78 DWORD_PTR cchLen = 0;
79
80 hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>( &cchLen));
81 ExitOnFailure(hr, "Failed to calculate length of string");
82
83 ++cchLen; // Add 1 for null-terminator
84
85 hr = StrAlloc(ppwz, cchLen);
86 ExitOnFailure(hr, "Failed to reallocate string");
87
88 LExit:
89 return hr;
90 }
91
92
93 /********************************************************************
94 StrTrimWhitespace - allocates or reuses dynamic string memory and copies
95 in an existing string, excluding whitespace
96
97 NOTE: caller is responsible for freeing ppwz even if function fails
98 ********************************************************************/
99 HRESULT DAPI StrTrimWhitespace(
100 __deref_out_z LPWSTR* ppwz,
101 __in_z LPCWSTR wzSource
102 )
103 {
104 HRESULT hr = S_OK;
105 int i = 0;
106 LPWSTR sczResult = NULL;
107
108 // Ignore beginning whitespace
109 while (L' ' == *wzSource || L'\t' == *wzSource)
110 {
111 wzSource++;
112 }
113
114 i = lstrlenW(wzSource);
115 // Overwrite ending whitespace with null characters
116 if (0 < i)
117 {
118 // start from the last non-null-terminator character in the array
119 for (i = i - 1; i > 0; --i)
120 {
121 if (L' ' != wzSource[i] && L'\t' != wzSource[i])
122 {
123 break;
124 }
125 }
126
127 ++i;
128 }
129
130 hr = StrAllocString(&sczResult, wzSource, i);
131 ExitOnFailure(hr, "Failed to copy result string");
132
133 // Output result
134 *ppwz = sczResult;
135 sczResult = NULL;
136
137 LExit:
138 ReleaseStr(sczResult);
139
140 return hr;
141 }
142
143
144
145
146
147 /********************************************************************
148 StrAllocString - allocates or reuses dynamic string memory and copies in an exis ting string
149
150 NOTE: caller is responsible for freeing ppwz even if function fails
151 NOTE: cchSource does not have to equal the length of wzSource
152 NOTE: if cchSource == 0, length of wzSource is used instead
153 ********************************************************************/
154 extern "C" HRESULT DAPI StrAllocString(
155 __deref_out_ecount_z(cchSource+1) LPWSTR* ppwz,
156 __in_z LPCWSTR wzSource,
157 __in DWORD_PTR cchSource
158 )
159 {
160 Assert(ppwz && wzSource); // && *wzSource);
161
162 HRESULT hr = S_OK;
163 DWORD_PTR cch = 0;
164
165 if (*ppwz)
166 {
167 cch = MemSize(*ppwz); // get the count in bytes so we can check if it f ailed (returns -1)
168 if (-1 == cch)
169 {
170 hr = E_INVALIDARG;
171 ExitOnFailure(hr, "failed to get size of destination string");
172 }
173 cch /= sizeof(WCHAR); //convert the count in bytes to count in characte rs
174 }
175
176 if (0 == cchSource)
177 {
178 cchSource = lstrlenW(wzSource);
179 }
180
181 DWORD_PTR cchNeeded;
182 hr = ::ULongPtrAdd(cchSource, 1, &cchNeeded); // add one for the null termin ator
183 ExitOnFailure(hr, "source string is too long");
184
185 if (cch < cchNeeded)
186 {
187 cch = cchNeeded;
188 hr = StrAlloc(ppwz, cch);
189 ExitOnFailure(hr, "failed to allocate string from string.");
190 }
191
192 // copy everything (the NULL terminator will be included)
193 hr = ::StringCchCopyNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STRSAF E_FILL_BEHIND_NULL);
194
195 LExit:
196 return hr;
197 }
198
199
200
201
202
203 /********************************************************************
204 StrAllocConcat - allocates or reuses dynamic string memory and adds an existing string
205
206 NOTE: caller is responsible for freeing ppwz even if function fails
207 NOTE: cchSource does not have to equal the length of wzSource
208 NOTE: if cchSource == 0, length of wzSource is used instead
209 ********************************************************************/
210 extern "C" HRESULT DAPI StrAllocConcat(
211 __deref_out_z LPWSTR* ppwz,
212 __in_z LPCWSTR wzSource,
213 __in DWORD_PTR cchSource
214 )
215 {
216 Assert(ppwz && wzSource); // && *wzSource);
217
218 HRESULT hr = S_OK;
219 DWORD_PTR cch = 0;
220 DWORD_PTR cchLen = 0;
221
222 if (*ppwz)
223 {
224 cch = MemSize(*ppwz); // get the count in bytes so we can check if it f ailed (returns -1)
225 if (-1 == cch)
226 {
227 hr = E_INVALIDARG;
228 ExitOnFailure(hr, "failed to get size of destination string");
229 }
230 cch /= sizeof(WCHAR); //convert the count in bytes to count in characte rs
231
232 hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PT R*>(&cchLen));
233 ExitOnFailure(hr, "Failed to calculate length of string");
234 }
235
236 Assert(cchLen <= cch);
237
238 if (0 == cchSource)
239 {
240 hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, reinterpret_cast<UINT _PTR*>(&cchSource));
241 ExitOnFailure(hr, "Failed to calculate length of string");
242 }
243
244 if (cch - cchLen < cchSource + 1)
245 {
246 cch = (cchSource + cchLen + 1) * 2;
247 hr = StrAlloc(ppwz, cch);
248 ExitOnFailure1(hr, "failed to allocate string from string: %ls", wzSourc e);
249 }
250
251 if (*ppwz)
252 {
253 hr = ::StringCchCatNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STR SAFE_FILL_BEHIND_NULL);
254 }
255 else
256 {
257 hr = E_UNEXPECTED;
258 ExitOnFailure(hr, "for some reason our buffer is still null");
259 }
260
261 LExit:
262 return hr;
263 }
264
265
266
267
268
269 /********************************************************************
270 StrAllocFormatted - allocates or reuses dynamic string memory and formats it
271
272 NOTE: caller is responsible for freeing ppwz even if function fails
273 ********************************************************************/
274 extern "C" HRESULT DAPI StrAllocFormatted(
275 __deref_out_z LPWSTR* ppwz,
276 __in __format_string LPCWSTR wzFormat,
277 ...
278 )
279 {
280 Assert(ppwz && wzFormat && *wzFormat);
281
282 HRESULT hr = S_OK;
283 va_list args;
284
285 va_start(args, wzFormat);
286 hr = StrAllocFormattedArgs(ppwz, wzFormat, args);
287 va_end(args);
288
289 return hr;
290 }
291
292
293
294
295 /********************************************************************
296 StrAllocFormattedArgs - allocates or reuses dynamic string memory
297 and formats it with the passed in args
298
299 NOTE: caller is responsible for freeing ppwz even if function fails
300 ********************************************************************/
301 extern "C" HRESULT DAPI StrAllocFormattedArgs(
302 __deref_out_z LPWSTR* ppwz,
303 __in __format_string LPCWSTR wzFormat,
304 __in va_list args
305 )
306 {
307 Assert(ppwz && wzFormat && *wzFormat);
308
309 HRESULT hr = S_OK;
310 DWORD_PTR cch = 0;
311 LPWSTR pwzOriginal = NULL;
312 DWORD_PTR cchOriginal = 0;
313
314 if (*ppwz)
315 {
316 cch = MemSize(*ppwz); // get the count in bytes so we can check if it f ailed (returns -1)
317 if (-1 == cch)
318 {
319 hr = E_INVALIDARG;
320 ExitOnFailure(hr, "failed to get size of destination string");
321 }
322 cch /= sizeof(WCHAR); //convert the count in bytes to count in characte rs
323
324 cchOriginal = lstrlenW(*ppwz);
325 }
326
327 if (0 == cch) // if there is no space in the string buffer
328 {
329 cch = 256;
330 hr = StrAlloc(ppwz, cch);
331 ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFormat) ;
332 }
333
334 // format the message (grow until it fits or there is a failure)
335 do
336 {
337 hr = ::StringCchVPrintfW(*ppwz, cch, wzFormat, args);
338 if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
339 {
340 if (!pwzOriginal)
341 {
342 // this allows you to pass the original string as a formatting a rgument and not crash
343 // save the original string and free it after the printf is comp lete
344 pwzOriginal = *ppwz;
345 *ppwz = NULL;
346 // StringCchVPrintfW starts writing to the string...
347 // NOTE: this hack only works with sprintf(&pwz, "%s ...", pwz, ...);
348 pwzOriginal[cchOriginal] = 0;
349 }
350 cch *= 2;
351 hr = StrAlloc(ppwz, cch);
352 ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFor mat);
353 hr = S_FALSE;
354 }
355 } while (S_FALSE == hr);
356 ExitOnFailure(hr, "failed to format string");
357
358 LExit:
359 ReleaseStr(pwzOriginal);
360
361 return hr;
362 }
363
364
365
366
367
368
369 /********************************************************************
370 StrMaxLength - returns maximum number of characters that can be stored in dynami c string p
371
372 NOTE: assumes Unicode string
373 ********************************************************************/
374 extern "C" HRESULT DAPI StrMaxLength(
375 __in LPCVOID p,
376 __out DWORD_PTR* pcch
377 )
378 {
379 Assert(pcch);
380
381 HRESULT hr = S_OK;
382
383 if (p)
384 {
385 *pcch = MemSize(p); // get size of entire buffer
386 if (-1 == *pcch)
387 {
388 ExitFunction1(hr = E_FAIL);
389 }
390
391 *pcch /= sizeof(WCHAR); // reduce to count of characters
392 }
393 else
394 {
395 *pcch = 0;
396 }
397 Assert(S_OK == hr);
398
399 LExit:
400 return hr;
401 }
402
403
404 /********************************************************************
405 StrSize - returns count of bytes in dynamic string p
406
407 ********************************************************************/
408 extern "C" HRESULT DAPI StrSize(
409 __in LPCVOID p,
410 __out DWORD_PTR* pcb
411 )
412 {
413 Assert(p && pcb);
414
415 HRESULT hr = S_OK;
416
417 *pcb = MemSize(p);
418 if (-1 == *pcb)
419 {
420 hr = E_FAIL;
421 }
422
423 return hr;
424 }
425
426 /********************************************************************
427 StrFree - releases dynamic string memory allocated by any StrAlloc*() functions
428
429 ********************************************************************/
430 extern "C" HRESULT DAPI StrFree(
431 __in LPVOID p
432 )
433 {
434 Assert(p);
435
436 HRESULT hr = MemFree(p);
437 ExitOnFailure(hr, "failed to free string");
438
439 LExit:
440 return hr;
441 }
442
443
444 /****************************************************************************
445 wcsistr - case insensitive find a substring
446
447 ****************************************************************************/
448 extern "C" LPCWSTR wcsistr(
449 __in_z LPCWSTR wzString,
450 __in_z LPCWSTR wzCharSet
451 )
452 {
453 LPCWSTR wzSource = wzString;
454 LPCWSTR wzSearch = NULL;
455 DWORD_PTR cchSourceIndex = 0;
456
457 // Walk through wzString (the source string) one character at a time
458 while (*wzSource)
459 {
460 cchSourceIndex = 0;
461 wzSearch = wzCharSet;
462
463 // Look ahead in the source string until we get a full match or we hit t he end of the source
464 while (L'\0' != wzSource[cchSourceIndex] && L'\0' != *wzSearch && towlow er(wzSource[cchSourceIndex]) == towlower(*wzSearch))
465 {
466 ++cchSourceIndex;
467 ++wzSearch;
468 }
469
470 // If we found it, return the point that we found it at
471 if (L'\0' == *wzSearch)
472 {
473 return wzSource;
474 }
475
476 // Walk ahead one character
477 ++wzSource;
478 }
479
480 return NULL;
481 }
482
483 /****************************************************************************
484 StrStringToInt16 - converts a string to a signed 16-bit integer.
485
486 ****************************************************************************/
487 extern "C" HRESULT DAPI StrStringToInt16(
488 __in_z LPCWSTR wzIn,
489 __in DWORD cchIn,
490 __out SHORT* psOut
491 )
492 {
493 HRESULT hr = S_OK;
494 LONGLONG ll = 0;
495
496 hr = StrStringToInt64(wzIn, cchIn, &ll);
497 ExitOnFailure(hr, "Failed to parse int64.");
498
499 if (SHORT_MAX < ll || SHORT_MIN > ll)
500 {
501 ExitFunction1(hr = DISP_E_OVERFLOW);
502 }
503 *psOut = (SHORT)ll;
504
505 LExit:
506 return hr;
507 }
508
509 /****************************************************************************
510 StrStringToUInt16 - converts a string to an unsigned 16-bit integer.
511
512 ****************************************************************************/
513 extern "C" HRESULT DAPI StrStringToUInt16(
514 __in_z LPCWSTR wzIn,
515 __in DWORD cchIn,
516 __out USHORT* pusOut
517 )
518 {
519 HRESULT hr = S_OK;
520 ULONGLONG ull = 0;
521
522 hr = StrStringToUInt64(wzIn, cchIn, &ull);
523 ExitOnFailure(hr, "Failed to parse uint64.");
524
525 if (USHORT_MAX < ull)
526 {
527 ExitFunction1(hr = DISP_E_OVERFLOW);
528 }
529 *pusOut = (USHORT)ull;
530
531 LExit:
532 return hr;
533 }
534
535 /****************************************************************************
536 StrStringToInt32 - converts a string to a signed 32-bit integer.
537
538 ****************************************************************************/
539 extern "C" HRESULT DAPI StrStringToInt32(
540 __in_z LPCWSTR wzIn,
541 __in DWORD cchIn,
542 __out INT* piOut
543 )
544 {
545 HRESULT hr = S_OK;
546 LONGLONG ll = 0;
547
548 hr = StrStringToInt64(wzIn, cchIn, &ll);
549 ExitOnFailure(hr, "Failed to parse int64.");
550
551 if (INT_MAX < ll || INT_MIN > ll)
552 {
553 ExitFunction1(hr = DISP_E_OVERFLOW);
554 }
555 *piOut = (INT)ll;
556
557 LExit:
558 return hr;
559 }
560
561 /****************************************************************************
562 StrStringToUInt32 - converts a string to an unsigned 32-bit integer.
563
564 ****************************************************************************/
565 extern "C" HRESULT DAPI StrStringToUInt32(
566 __in_z LPCWSTR wzIn,
567 __in DWORD cchIn,
568 __out UINT* puiOut
569 )
570 {
571 HRESULT hr = S_OK;
572 ULONGLONG ull = 0;
573
574 hr = StrStringToUInt64(wzIn, cchIn, &ull);
575 ExitOnFailure(hr, "Failed to parse uint64.");
576
577 if (UINT_MAX < ull)
578 {
579 ExitFunction1(hr = DISP_E_OVERFLOW);
580 }
581 *puiOut = (UINT)ull;
582
583 LExit:
584 return hr;
585 }
586
587 /****************************************************************************
588 StrStringToInt64 - converts a string to a signed 64-bit integer.
589
590 ****************************************************************************/
591 extern "C" HRESULT DAPI StrStringToInt64(
592 __in_z LPCWSTR wzIn,
593 __in DWORD cchIn,
594 __out LONGLONG* pllOut
595 )
596 {
597 HRESULT hr = S_OK;
598 DWORD i = 0;
599 INT iSign = 1;
600 INT nDigit = 0;
601 LARGE_INTEGER liValue = { };
602
603 // get string length if not provided
604 if (0 >= cchIn)
605 {
606 cchIn = lstrlenW(wzIn);
607 if (0 >= cchIn)
608 {
609 ExitFunction1(hr = E_INVALIDARG);
610 }
611 }
612
613 // check sign
614 if (L'-' == wzIn[0])
615 {
616 if (1 >= cchIn)
617 {
618 ExitFunction1(hr = E_INVALIDARG);
619 }
620 i = 1;
621 iSign = -1;
622 }
623
624 // read digits
625 while (i < cchIn)
626 {
627 nDigit = wzIn[i] - L'0';
628 if (0 > nDigit || 9 < nDigit)
629 {
630 ExitFunction1(hr = E_INVALIDARG);
631 }
632 liValue.QuadPart = liValue.QuadPart * 10 + nDigit * iSign;
633
634 if ((liValue.HighPart ^ iSign) & INT_MIN)
635 {
636 ExitFunction1(hr = DISP_E_OVERFLOW);
637 }
638 ++i;
639 }
640
641 *pllOut = liValue.QuadPart;
642
643 LExit:
644 return hr;
645 }
646
647 /****************************************************************************
648 StrStringToUInt64 - converts a string to an unsigned 64-bit integer.
649
650 ****************************************************************************/
651 extern "C" HRESULT DAPI StrStringToUInt64(
652 __in_z LPCWSTR wzIn,
653 __in DWORD cchIn,
654 __out ULONGLONG* pullOut
655 )
656 {
657 HRESULT hr = S_OK;
658 DWORD i = 0;
659 DWORD nDigit = 0;
660 ULONGLONG ullValue = 0;
661 ULONGLONG ull = 0;
662
663 // get string length if not provided
664 if (0 >= cchIn)
665 {
666 cchIn = lstrlenW(wzIn);
667 if (0 >= cchIn)
668 {
669 ExitFunction1(hr = E_INVALIDARG);
670 }
671 }
672
673 // read digits
674 while (i < cchIn)
675 {
676 nDigit = wzIn[i] - L'0';
677 if (9 < nDigit)
678 {
679 ExitFunction1(hr = E_INVALIDARG);
680 }
681 ull = (ULONGLONG)(ullValue * 10 + nDigit);
682
683 if (ull < ullValue)
684 {
685 ExitFunction1(hr = DISP_E_OVERFLOW);
686 }
687 ullValue = ull;
688 ++i;
689 }
690
691 *pullOut = ullValue;
692
693 LExit:
694 return hr;
695 }
696
697 /****************************************************************************
698 StrStringToUpper - alters the given string in-place to be entirely uppercase
699
700 ****************************************************************************/
701 void DAPI StrStringToUpper(
702 __inout_z LPWSTR wzIn
703 )
704 {
705 ::CharUpperBuffW(wzIn, lstrlenW(wzIn));
706 }
707
708 /****************************************************************************
709 StrStringToLower - alters the given string in-place to be entirely lowercase
710
711 ****************************************************************************/
712 void DAPI StrStringToLower(
713 __inout_z LPWSTR wzIn
714 )
715 {
716 ::CharLowerBuffW(wzIn, lstrlenW(wzIn));
717 }
718
719
720
721
722 /****************************************************************************
723 StrAllocStringMapInvariant - helper function for the ToUpper and ToLower.
724
725 Note: Assumes source and destination buffers will be the same.
726 ****************************************************************************/
727 static HRESULT StrAllocStringMapInvariant(
728 __deref_out_z LPWSTR* pscz,
729 __in_z LPCWSTR wzSource,
730 __in int cchSource,
731 __in DWORD dwMapFlags
732 )
733 {
734 HRESULT hr = S_OK;
735
736 hr = StrAllocString(pscz, wzSource, cchSource);
737 ExitOnFailure(hr, "Failed to allocate a copy of the source string.");
738
739 if (0 == cchSource)
740 {
741 // Need the actual string size for LCMapString. This includes the null-t erminator
742 // but LCMapString doesn't care either way.
743 hr = ::StringCchLengthW(*pscz, INT_MAX, reinterpret_cast<size_t*>(&cchSo urce));
744 ExitOnFailure(hr, "Failed to get the length of the string.");
745 }
746
747 // Convert the copy of the string to upper or lower case in-place.
748 if (0 == ::LCMapStringW(LOCALE_INVARIANT, dwMapFlags, *pscz, cchSource, *psc z, cchSource))
749 {
750 ExitWithLastError(hr, "Failed to convert the string case.");
751 }
752
753 LExit:
754 return hr;
755 }
OLDNEW

Powered by Google App Engine
This is Rietveld