CFugue
StrUtils.h
1 #ifndef __STRUTILS_H__91CD1AE9_5C86_4261_AB5D_BDDAFBDA8DC5
2 #define __STRUTILS_H__91CD1AE9_5C86_4261_AB5D_BDDAFBDA8DC5
3 
4 #include "_TChar.h" // On Non win32 platforms we use a local TChar.h
5 
6 ///
7 /// Before including this file #Define STRUTILS_RETURN_TYPE to use that type as the default return type.
8 /// For example, to use _bstr_t as the return type, #define STRUTILS_RETURN_TYPE _bstr_t
9 ///
10 #ifndef STRUTILS_RETURN_TYPE
11 #include "MString.h"
12 #define STRUTILS_RETURN_TYPE CFugue::MString
13 #endif
14 
15 #include <stdio.h>
16 
17 #pragma warning(push)
18 #pragma warning(disable:4996) // sprintf deprecated warning: disable;
19 
20 namespace OIL
21 {
22 
23 #if !defined(_W64)
24 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
25 #define _W64 __w64
26 #else
27 #define _W64
28 #endif
29 #endif
30 
31 #if defined(_WIN64)
32  typedef __int64 INT_PTR, *PINT_PTR;
33  typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
34 
35  typedef __int64 LONG_PTR, *PLONG_PTR;
36  typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
37 
38  #define __int3264 __int64
39 
40 #else
41  typedef _W64 int INT_PTR, *PINT_PTR;
42  typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
43 
44  typedef _W64 long LONG_PTR, *PLONG_PTR;
45  typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
46 
47  #define __int3264 __int32
48 
49 #endif
50 
51  typedef STRUTILS_RETURN_TYPE StrUtils_Return_Type;
52 
53 #if !defined(_countof)
54 #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
55 #endif
56 
57 #if defined __GNUC__ && defined __STRICT_ANSI__
58  #define PRINTNUM(BUF,SPEC,NUM) _stprintf(BUF,_countof(BUF),SPEC,NUM) // swprint is by default a secure version !!
59 #elif defined __GNUC__ && !defined __STRICT_ANSI__
60  #define PRINTNUM(BUF,SPEC,NUM) _stprintf(BUF,SPEC,NUM) // Gcc does not have a secure version of sprintf
61 #elif defined _MSC_VER
62  #define PRINTNUM(BUF,SPEC,NUM) _stprintf_s(BUF,_countof(BUF),SPEC,NUM) //MSVC has different Secure version
63 #endif // __GNUC__
64 
65 #define BUFExtra 4
66 #define GetBufSizeForType(xType) ((sizeof(xType)*8) + BUFExtra) // We need extra for space and any other chars (such as 0x)
67 
68 #define DEFAULT_WIDTH -1
69 #define DEFAULT_FILLER _T('0')
70 #define DEFAULT_RADIX 10
71 #define DEFAULT_PREFIXUSAGE true
72 
73 // Converts the given number to its positive form
74 template<typename TNumberType>
75 inline TNumberType _abs(TNumberType number) { return( number>=0 ? number : -number ); }
76 
77 // Converts the given unsigned number to String. Only integral types are supported.
78 template<typename TNumberType>
79 StrUtils_Return_Type UnSignedNumber2Str(const TNumberType TNumber, // Number that should be converted to string
80  int Width = DEFAULT_WIDTH, // Width of the output
81  TCHAR FillWith = DEFAULT_FILLER, // The character that should be used to fill the width, if any
82  int Radix = DEFAULT_RADIX, // Base of the representation
83  bool bPrefixRadix=DEFAULT_PREFIXUSAGE // Should the output contain "0x" "0b" prefixes
84  )
85 {
86  TCHAR buf[GetBufSizeForType(TNumberType)];
87 
88  TCHAR* pText = buf + _countof(buf) - 1; /* we want to start the last digit at the end of the buffer */
89 
90  *pText-- = _T('\0');
91 
92  if(Width >= (_countof(buf) - 2))
93  Width = DEFAULT_WIDTH;
94 
95  TNumberType nNumber = TNumber;
96 
97  do{
98  int digit = (int)(nNumber % Radix);
99 
100  nNumber /= Radix; /* reduce number */
101 
102  if (digit >= 10)/* if hex digit, make it a letter */
103  digit = (digit - 10 + (int)_T('A'));
104  else
105  digit = digit + (int)_T('0');
106 
107  *pText-- = (TCHAR)digit; /* store the digit */
108 
109  if(Width != DEFAULT_WIDTH)
110  if(--Width == 0) break;
111 
112  } while (nNumber != 0);
113 
114  if(Width != DEFAULT_WIDTH)
115  while(Width-- != 0 && pText != buf)
116  *pText-- = FillWith; // Fill the Text with the Fill Character
117 
118  if(bPrefixRadix && Radix == 16)
119  {
120  *pText-- = _T('x');
121  *pText-- = _T('0');
122  }
123  if(bPrefixRadix && Radix == 2)
124  {
125  *pText-- = _T('b');
126  *pText-- = _T('0');
127  }
128 
129  ++pText; /* text points to first digit now */
130 
131  return pText;
132 }
133 
134 // Converts the given signed number to String. Only integral types are supported.
135 template<typename TNumberType>
136 StrUtils_Return_Type SignedNumber2Str(const TNumberType TNumber, // Number that should be converted to string
137  int Width = DEFAULT_WIDTH, // Width of the output
138  TCHAR FillWith = DEFAULT_FILLER, // The character that should be used to fill the width, if any
139  int Radix = DEFAULT_RADIX, // Base of the representation
140  bool bPrefixRadix=DEFAULT_PREFIXUSAGE, // Should the output contain "0x" "0b" prefixes
141  bool bSpaceForSign = true // Should empty space be inserted for Sign when number is positive
142  )
143 {
144  TCHAR buf[GetBufSizeForType(TNumberType)];
145 
146  TCHAR* pText = buf + _countof(buf) - 1; /* we want start the last digit at end of buffer */
147 
148  *pText-- = _T('\0');
149 
150  if(Width >= (_countof(buf) - 2))
151  Width = DEFAULT_WIDTH;
152 
153  TNumberType nNumber = _abs<TNumberType>(TNumber);
154 
155  do{
156  int digit = _abs<int>((int)(nNumber % Radix));
157 
158  nNumber /= Radix; /* reduce number */
159 
160  if (digit >= 10)/* if hex digit, make it a letter */
161  digit = (digit - 10 + (int)_T('A'));
162  else
163  digit = digit + (int)_T('0');
164 
165  *pText-- = (TCHAR)digit; /* store the digit */
166 
167  if(Width != DEFAULT_WIDTH)
168  if(--Width == 0) break;
169 
170  } while (nNumber != 0);
171 
172  if(Width != DEFAULT_WIDTH)
173  while(Width-- != 0 && pText != buf)
174  *pText-- = FillWith; // Fill the Text with the Fill Character
175 
176  if(TNumber < (TNumberType)0) // Take care of the sign
177  {
178  *pText-- = _T('-');
179  }
180  else
181  {
182  if(bSpaceForSign) *pText-- = _T(' ');
183  }
184 
185  if(bPrefixRadix && Radix == 16)
186  {
187  *pText-- = _T('x');
188  *pText-- = _T('0');
189  }
190  if(bPrefixRadix && Radix == 2)
191  {
192  *pText-- = _T('b');
193  *pText-- = _T('0');
194  }
195 
196  ++pText; /* text points to first digit now */
197 
198  return pText;
199 }
200 
201 
202 
203 
204 // This default method is the base for all specializations that later follow.
205 // In an ideal situation, this should never be called. If
206 // this is being called, then it indicates that we have a type
207 // that doesn't have a correct specialized form. In such case
208 // we can either choose to specialize ToString() for that type, or
209 // let this defualt method return an empty string.
210 template<typename T>
211 inline StrUtils_Return_Type ToString(const T& Arg)
212 {
213  return _T("");
214 }
215 
216 // This form of ToString() acts as base for all custom pointer types.
217 // While this looks simple, it is very powerful, as it can take care of
218 // pointer-to-pointer types, pointer-to-pointer-to-pointer types and so on.
219 // As a Plus, this can takes care of expanding the 'content' also.
220 template<typename T>
221 inline StrUtils_Return_Type ToString(const T* pArg)
222 {
223 // Disable warning: "A qualifier, such as const, is applied to a function type defined by typedef"
224 #pragma warning(push)
225 #pragma warning(disable:4180)
226 
227  // We have got a pointer to be converted to a string.
228  // Lets see if we can represent the content also as string.
229  if(pArg != NULL)
230  {
231  //StrUtils_Return_Type strArgContent = ToString((const T&)*pArg);
232 
233  //// Lets check if we got valid content (to add braces around it)
234  //LPCTSTR lpszContent = (LPCTSTR)strArgContent;
235 
236  //if(lpszContent != NULL && *lpszContent != _T('\0'))
237  //{
238  // // Add braces around the content only if they are not already present.
239  // // For simplicity we check only for start brace in the content. If we
240  // // see a start brace we assume that the end brace is also present at
241  // // the end. This need not be a invalid assumption - but we ignore it for now.
242  // LPCTSTR szStartBrace = (*lpszContent != _T('{') ? _T("{") : _T(""));
243  // LPCTSTR szEndBrace = (*lpszContent != _T('{') ? _T("}") : _T(""));
244 
245  // return ToString((const void*)pArg) + szStartBrace + strArgContent + szEndBrace;
246  //}
247  }
248 
249  // Seems we have got a NULL pointer. We can simply return "0x00000000" directly. But
250  // we choose to use ToString() to ensure the correct number of zeroes in the output.
251  return ToString((const void*)pArg);
252 
253 #pragma warning(pop) // disable:4180
254 }
255 
256 template<typename T>
257 inline StrUtils_Return_Type ToString(T* pArg)
258 {
259  return ToString((const T*) pArg);
260 }
261 
262 template<>
263 inline StrUtils_Return_Type ToString(const bool& bVal)
264 {
265  return bVal ? _T("True") : _T("False");
266 }
267 
268 template<>
269 inline StrUtils_Return_Type ToString(const unsigned short& nNumber)
270 {
271  return UnSignedNumber2Str(nNumber);
272 }
273 
274 template<>
275 inline StrUtils_Return_Type ToString(const signed short& nNumber)
276 {
277  return SignedNumber2Str(nNumber);
278 }
279 
280 template<>
281 inline StrUtils_Return_Type ToString(const unsigned int& nNumber)
282 {
283  return UnSignedNumber2Str(nNumber);
284 }
285 
286 template<>
287 inline StrUtils_Return_Type ToString(const signed int& nNumber)
288 {
289  return SignedNumber2Str(nNumber);
290 }
291 
292 template<>
293 inline StrUtils_Return_Type ToString(const unsigned long& lNumber)
294 {
295  return UnSignedNumber2Str(lNumber);
296 }
297 
298 template<>
299 inline StrUtils_Return_Type ToString(const signed long& lNumber)
300 {
301  return SignedNumber2Str(lNumber);
302 }
303 
304 template<>
305 inline StrUtils_Return_Type ToString(const float& fNumber)
306 {
307 //#if defined _UNICODE || defined UNICODE
308 // return std::to_wstring(fNumber);
309 //#else
310 // return std::to_string(fNumber);
311 //#endif
312  TCHAR sz[GetBufSizeForType(fNumber)];
313  PRINTNUM(sz,_T("% 0.2f"),fNumber);
314  return sz;
315 }
316 
317 template<>
318 inline StrUtils_Return_Type ToString(const double& fNumber)
319 {
320  return ToString((const float) fNumber);
321 }
322 
323 template<>
324 inline StrUtils_Return_Type ToString(const char& ch)
325 {
326  StrUtils_Return_Type str;
327  //const char str[2] = {(char)ch, '\0'};
328  //return ToString((const int)ch) + _T("'") + StrUtils_Return_Type(str) + _T("'");
329  str << (const int)ch << _T("'") << StrUtils_Return_Type(str) << _T("'");
330  return str;
331 }
332 
333 template<>
334 inline StrUtils_Return_Type ToString(const unsigned char& ch)
335 {
336  StrUtils_Return_Type str;
337  //const char str[2] = {(char)ch, '\0'};
338  //return ToString((const unsigned int)ch) + _T("'") + StrUtils_Return_Type(str) + _T("'");
339  str << (const unsigned int)ch + _T("'") + StrUtils_Return_Type(str) + _T("'");
340  return str;
341 }
342 
343 #ifdef _NATIVE_WCHAR_T_DEFINED
344 template<>
345 inline StrUtils_Return_Type ToString(const wchar_t& wch)
346 {
347  const wchar_t wstr[2] = {wch, L'\0'};
348  return ToString((const int)wch) + _T("'") + StrUtils_Return_Type(wstr) + _T("'");
349 }
350 #endif
351 
352 template<>
353 inline StrUtils_Return_Type ToString(const char* sz)
354 {
355  StrUtils_Return_Type str;
356  str << _T("\"") << StrUtils_Return_Type(sz) << _T("\"");
357  return str;
358 }
359 template<>
360 inline StrUtils_Return_Type ToString(char* sz)
361 {
362  return ToString((const char*)sz);
363 }
364 
365 template<>
366 inline StrUtils_Return_Type ToString(const wchar_t* wsz)
367 {
368  StrUtils_Return_Type str;
369  str << _T("\"") << StrUtils_Return_Type(wsz) << _T("\"");
370  return str;
371 }
372 template<>
373 inline StrUtils_Return_Type ToString(wchar_t* wsz)
374 {
375  return ToString((const wchar_t*)wsz);
376 }
377 
378 template<>
379 inline StrUtils_Return_Type ToString(const void* pVoid)
380 {
381 #pragma warning(push)
382 #pragma warning(disable:4244) // Disable the nasty "LPVOID to Unsigned long" conversion warning
383  return UnSignedNumber2Str(reinterpret_cast<ULONG_PTR>(pVoid), sizeof(ULONG_PTR) * 2, DEFAULT_FILLER, 16);
384 #pragma warning(pop)
385 }
386 template<>
387 inline StrUtils_Return_Type ToString(void* pVoid)
388 {
389  return ToString((const void*)pVoid);
390 }
391 
392 #if defined(_VECTOR_) // if included <vector>
393 template<typename T>
394 inline StrUtils_Return_Type ToString(const std::vector<T>& Container, const TCHAR* lpszSeperator = _T(","), const TCHAR* lpszBegin=_T("{"), const TCHAR* lpszEnd=_T("}"))
395 {
396  StrUtils_Return_Type Str(lpszBegin);
397 
398  std::vector<T>::const_iterator iter = Container.begin();
399  std::vector<T>::const_iterator iterEnd = Container.end();
400 
401  if(iter != iterEnd)
402  Str += ToString(*iter++);
403 
404  while(iter != iterEnd)
405  Str += lpszSeperator + ToString(*iter++);
406 
407  return Str + lpszEnd;
408 }
409 #endif // if defined(_VECTOR_)
410 
411 #if defined(_LIST_) // if included <list>
412 template<typename T>
413 inline StrUtils_Return_Type ToString(const std::list<T>& Container, const TCHAR* lpszSeperator = _T(","), const TCHAR* lpszBegin=_T("{"), const TCHAR* lpszEnd=_T("}"))
414 {
415  StrUtils_Return_Type Str(lpszBegin);
416 
417  std::list<T>::const_iterator iter = Container.begin();
418  std::list<T>::const_iterator iterEnd = Container.end();
419 
420  if(iter != iterEnd)
421  Str += ToString(*iter++);
422 
423  while(iter != iterEnd)
424  Str += lpszSeperator + ToString(*iter++);
425 
426  return Str + lpszEnd;
427 }
428 #endif // if defined(_LIST_)
429 
430 #if defined(_MAP_) // if included <map>
431 template<typename K, typename T>
432 inline StrUtils_Return_Type ToString(const std::map<K, T>& Container, const TCHAR* lpszSeperator = _T(","), const TCHAR* lpszBegin=_T("{"), const TCHAR* lpszEnd=_T("}"))
433 {
434  StrUtils_Return_Type Str(lpszBegin);
435 
436  std::map<K, T>::const_iterator iter = Container.begin();
437  std::map<K, T>::const_iterator iterEnd = Container.end();
438 
439  if(iter != iterEnd)
440  {
441  Str += _T("(") + ToString(iter->first) + lpszSeperator + ToString(iter->second) + _T(")");
442  ++iter;
443  }
444 
445  while(iter != iterEnd)
446  {
447  Str += lpszSeperator + _T("(") + ToString(iter->first) + lpszSeperator + ToString(iter->second) + _T(")");
448  ++iter;
449  }
450 
451  return Str + lpszEnd;
452 }
453 #endif // if defined(_MAP_)
454 
455 } // namespace OIL
456 
457 #pragma warning(pop)
458 
459 #endif // ifdef __STRUTILS_H__91CD1AE9_5C86_4261_AB5D_BDDAFBDA8DC5

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem