1
2 // Null ptr and buffer overflow safe C string primitives.
3
4 #include "assertive.h"
5 #include <climits>
6 #include <cstdarg>
7 #include <cstdlib>
8 #include <cstring>
9 #include <wchar.h>
10 #include "ss.h"
11
ssalloc(size_t count)12 wchar_t* ssalloc(size_t count)
13 {
14 wchar_t* d = 0;
15 if(count)
16 {
17 d = static_cast<wchar_t*>(malloc(count*sizeof(d[0])));
18 if(d)
19 {
20 d[0] = 0;
21 }
22 }
23 return d;
24 }
25
ssdup(const wchar_t * s)26 wchar_t* ssdup(const wchar_t* s)
27 {
28 wchar_t* d = 0;
29 if(s)
30 {
31 d = _wcsdup(s);
32 }
33 return d;
34 }
35
ssdupn(const wchar_t * s,size_t len)36 wchar_t* ssdupn(const wchar_t* s,size_t len)
37 {
38 wchar_t* d = 0;
39 if(s)
40 {
41 d = ssalloc(len+1);
42 if(d)
43 {
44 memcpy(d,s,len*sizeof(s[0]));
45 d[len] = 0;
46 }
47 }
48 return d;
49 }
50
sscmpi(const wchar_t * s1,const wchar_t * s2)51 int sscmpi(const wchar_t* s1,const wchar_t* s2)
52 {
53 return _wcsicmp(ssfix(s1),ssfix(s2));
54 }
55
ssrchr(const wchar_t * s,wchar_t c)56 wchar_t* ssrchr(const wchar_t* s,wchar_t c)
57 {
58 wchar_t* d = 0;
59 if(s)
60 {
61 d = const_cast<wchar_t*>(wcsrchr(s,c));
62 }
63 return d;
64 }
65
ssconvalloc(const wchar_t * s)66 char* ssconvalloc(const wchar_t* s)
67 {
68 char* d = 0;
69 size_t c;
70 if(s)
71 {
72 c = wcstombs(0,s,0);
73 if(c < INT_MAX)
74 {
75 d = static_cast<char*>(malloc((c+1)*sizeof(d[0])));
76 if(d)
77 {
78 VERIFYIS(wcstombs(d,s,c+1),c);
79 d[c] = 0;
80 }
81 }
82 }
83 return d;
84 }
85
ssconvalloc(const char * s)86 wchar_t* ssconvalloc(const char* s)
87 {
88 wchar_t* d = 0;
89 size_t c;
90 if(s)
91 {
92 c = mbstowcs(0,s,0);
93 if(c < INT_MAX)
94 {
95 d = static_cast<wchar_t*>(malloc((c+1)*sizeof(d[0])));
96 if(d)
97 {
98 VERIFYIS(mbstowcs(d,s,c+1),c);
99 d[c] = 0;
100 }
101 }
102 }
103 return d;
104 }
105
ssvformat(wchar_t * dest,size_t maxDestChars,const wchar_t * format,va_list args)106 void ssvformat(wchar_t* dest,size_t maxDestChars,const wchar_t* format,
107 va_list args)
108 {
109 if(dest && maxDestChars)
110 {
111 _vsnwprintf(dest,maxDestChars,format,args);
112 dest[maxDestChars-1] = 0;
113 }
114 }
115
ssformat(wchar_t * dest,size_t maxDestChars,const wchar_t * format,...)116 void ssformat(wchar_t* dest,size_t maxDestChars,const wchar_t* format,...)
117 {
118 va_list args;
119 va_start(args,format);
120 ssvformat(dest,maxDestChars,format,args);
121 }
122
ssvformatalloc(const wchar_t * format,va_list args)123 wchar_t* ssvformatalloc(const wchar_t* format,va_list args)
124 {
125 static const size_t maxStackScratchChars = 300;
126 wchar_t stackScratch[maxStackScratchChars] = L"";
127 wchar_t* heapScratch = 0;
128 wchar_t* scratch = stackScratch;
129 size_t maxScratchChars = maxStackScratchChars;
130 int count;
131 bool again;
132 wchar_t* val = 0;
133
134 do
135 {
136 again = false;
137 count = _vsnwprintf(scratch,maxScratchChars,format,args);
138 if(count < 0 || static_cast<unsigned>(count) >= maxScratchChars)
139 {
140 free(heapScratch);
141 maxScratchChars = maxScratchChars*2+5000;
142 scratch = heapScratch = ssalloc(maxScratchChars);
143 if(heapScratch)
144 {
145 again = true;
146 }
147 }
148 } while(again);
149
150 if(scratch)
151 {
152 val = _wcsdup(scratch);
153 }
154 free(heapScratch);
155 return val;
156 }
157