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