Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/vr/openvr/src/strtools_public.cpp
Line
Count
Source (jump to first uncovered line)
1
//========= Copyright Valve Corporation ============//
2
#include "strtools_public.h"
3
#include <string.h>
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <sstream>
7
#include <iostream>
8
9
//-----------------------------------------------------------------------------
10
// Purpose:
11
//-----------------------------------------------------------------------------
12
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
13
0
{
14
0
  return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
15
0
}
16
17
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
18
0
{
19
0
  return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
20
0
}
21
22
23
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
24
0
{
25
0
  size_t cStrLen = sString.length();
26
0
  size_t cSuffixLen = sSuffix.length();
27
0
28
0
  if ( cSuffixLen > cStrLen )
29
0
    return false;
30
0
31
0
  std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
32
0
33
0
  return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
34
0
}
35
36
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
37
0
{
38
0
  size_t cStrLen = sString.length();
39
0
  size_t cSuffixLen = sSuffix.length();
40
0
41
0
  if ( cSuffixLen > cStrLen )
42
0
    return false;
43
0
44
0
  std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
45
0
46
0
  return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
47
0
}
48
49
//-----------------------------------------------------------------------------
50
// Purpose:
51
//-----------------------------------------------------------------------------
52
std::string UTF16to8(const wchar_t * in)
53
0
{
54
0
  std::string out;
55
0
  unsigned int codepoint = 0;
56
0
  for ( ; in && *in != 0; ++in )
57
0
  {
58
0
    if (*in >= 0xd800 && *in <= 0xdbff)
59
0
      codepoint = ((*in - 0xd800) << 10) + 0x10000;
60
0
    else
61
0
    {
62
0
      if (*in >= 0xdc00 && *in <= 0xdfff)
63
0
        codepoint |= *in - 0xdc00;
64
0
      else
65
0
        codepoint = *in;
66
0
67
0
      if (codepoint <= 0x7f)
68
0
        out.append(1, static_cast<char>(codepoint));
69
0
      else if (codepoint <= 0x7ff)
70
0
      {
71
0
        out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
72
0
        out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
73
0
      }
74
0
      else if (codepoint <= 0xffff)
75
0
      {
76
0
        out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
77
0
        out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
78
0
        out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
79
0
      }
80
0
      else
81
0
      {
82
0
        out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
83
0
        out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
84
0
        out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
85
0
        out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
86
0
      }
87
0
      codepoint = 0;
88
0
    }
89
0
  }
90
0
  return out;
91
0
}
92
93
std::wstring UTF8to16(const char * in)
94
0
{
95
0
  std::wstring out;
96
0
  unsigned int codepoint = 0;
97
0
  int following = 0;
98
0
  for ( ; in && *in != 0; ++in )
99
0
  {
100
0
    unsigned char ch = *in;
101
0
    if (ch <= 0x7f)
102
0
    {
103
0
      codepoint = ch;
104
0
      following = 0;
105
0
    }
106
0
    else if (ch <= 0xbf)
107
0
    {
108
0
      if (following > 0)
109
0
      {
110
0
        codepoint = (codepoint << 6) | (ch & 0x3f);
111
0
        --following;
112
0
      }
113
0
    }
114
0
    else if (ch <= 0xdf)
115
0
    {
116
0
      codepoint = ch & 0x1f;
117
0
      following = 1;
118
0
    }
119
0
    else if (ch <= 0xef)
120
0
    {
121
0
      codepoint = ch & 0x0f;
122
0
      following = 2;
123
0
    }
124
0
    else
125
0
    {
126
0
      codepoint = ch & 0x07;
127
0
      following = 3;
128
0
    }
129
0
    if (following == 0)
130
0
    {
131
0
      if (codepoint > 0xffff)
132
0
      {
133
0
        out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
134
0
        out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
135
0
      }
136
0
      else
137
0
        out.append(1, static_cast<wchar_t>(codepoint));
138
0
      codepoint = 0;
139
0
    }
140
0
  }
141
0
  return out;
142
0
}
143
144
145
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
146
0
{
147
0
  strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
148
0
  pchBuffer[unBufferSizeBytes - 1] = '\0';
149
0
}
150
151
152
// --------------------------------------------------------------------
153
// Purpose: converts a string to upper case
154
// --------------------------------------------------------------------
155
std::string StringToUpper( const std::string & sString )
156
0
{
157
0
  std::string sOut;
158
0
  sOut.reserve( sString.size() + 1 );
159
0
  for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
160
0
  {
161
0
    sOut.push_back( (char)toupper( *i ) );
162
0
  }
163
0
164
0
  return sOut;
165
0
}
166
167
168
// --------------------------------------------------------------------
169
// Purpose: converts a string to lower case
170
// --------------------------------------------------------------------
171
std::string StringToLower( const std::string & sString )
172
0
{
173
0
  std::string sOut;
174
0
  sOut.reserve( sString.size() + 1 );
175
0
  for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
176
0
  {
177
0
    sOut.push_back( (char)tolower( *i ) );
178
0
  }
179
0
180
0
  return sOut;
181
0
}
182
183
184
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
185
0
{
186
0
  uint32_t unLen = (uint32_t)sValue.length() + 1;
187
0
  if( !pchBuffer || !unBufferLen )
188
0
    return unLen;
189
0
190
0
  if( unBufferLen < unLen )
191
0
  {
192
0
    pchBuffer[0] = '\0';
193
0
  }
194
0
  else
195
0
  {
196
0
    memcpy( pchBuffer, sValue.c_str(), unLen );
197
0
  }
198
0
199
0
  return unLen;
200
0
}
201
202
// Commented out by Mozilla, please see README.mozilla
203
/** Returns a std::string from a uint64_t */
204
/*
205
std::string Uint64ToString( uint64_t ulValue )
206
{
207
  char buf[ 22 ];
208
#if defined( _WIN32 )
209
  sprintf_s( buf, "%llu", ulValue );
210
#else
211
    snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
212
#endif
213
  return buf;
214
}
215
*/
216
217
/** returns a uint64_t from a string */
218
uint64_t StringToUint64( const std::string & sValue )
219
0
{
220
0
  return strtoull( sValue.c_str(), NULL, 0 );
221
0
}
222
223
//-----------------------------------------------------------------------------
224
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
225
//-----------------------------------------------------------------------------
226
char cIntToHexDigit( int nValue )
227
0
{
228
0
  //Assert( nValue >= 0 && nValue <= 15 );
229
0
  return "0123456789ABCDEF"[ nValue & 15 ];
230
0
}
231
232
//-----------------------------------------------------------------------------
233
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
234
//          is not a valid hex digit.
235
//-----------------------------------------------------------------------------
236
int iHexCharToInt( char cValue )
237
0
{
238
0
  int32_t iValue = cValue;
239
0
  if ( (uint32_t)( iValue - '0' ) < 10 )
240
0
    return iValue - '0';
241
0
242
0
  iValue |= 0x20;
243
0
  if ( (uint32_t)( iValue - 'a' ) < 6 )
244
0
    return iValue - 'a' + 10;
245
0
246
0
  return -1;
247
0
}
248
249
//-----------------------------------------------------------------------------
250
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
251
//          with spaces turned to + like HTML form encoding.
252
//-----------------------------------------------------------------------------
253
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
254
0
{
255
0
  //AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
256
0
  
257
0
  int iDestPos = 0;
258
0
  for ( int i=0; i < nSourceLen; ++i )
259
0
  {
260
0
    // worst case we need 3 additional chars
261
0
    if( (iDestPos+3) > nDestLen  )
262
0
    {
263
0
      pchDest[0] = '\0';
264
0
//      AssertMsg( false, "Target buffer too short\n" );
265
0
      return;
266
0
    }
267
0
268
0
    // We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
269
0
    // These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
270
0
    // Current specs also allow '~', but that is forbidden under original RFC 1738.
271
0
    if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
272
0
       && pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'  
273
0
    )
274
0
    {
275
0
      if ( bUsePlusForSpace && pchSource[i] == ' ' )
276
0
      {
277
0
        pchDest[iDestPos++] = '+';
278
0
      }
279
0
      else
280
0
      {
281
0
        pchDest[iDestPos++] = '%';
282
0
        uint8_t iValue = pchSource[i];
283
0
        if ( iValue == 0 )
284
0
        {
285
0
          pchDest[iDestPos++] = '0';
286
0
          pchDest[iDestPos++] = '0';
287
0
        }
288
0
        else
289
0
        {
290
0
          char cHexDigit1 = cIntToHexDigit( iValue % 16 );
291
0
          iValue /= 16;
292
0
          char cHexDigit2 = cIntToHexDigit( iValue );
293
0
          pchDest[iDestPos++] = cHexDigit2;
294
0
          pchDest[iDestPos++] = cHexDigit1;
295
0
        }
296
0
      }
297
0
    }
298
0
    else
299
0
    {
300
0
      pchDest[iDestPos++] = pchSource[i];
301
0
    }
302
0
  }
303
0
304
0
  if( (iDestPos+1) > nDestLen )
305
0
  {
306
0
    pchDest[0] = '\0';
307
0
    //AssertMsg( false, "Target buffer too short to terminate\n" );
308
0
    return;
309
0
  }
310
0
311
0
  // Null terminate
312
0
  pchDest[iDestPos++] = 0;
313
0
}
314
315
316
//-----------------------------------------------------------------------------
317
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
318
//          with spaces turned to + like HTML form encoding.
319
//
320
//      Returns the amount of space used in the output buffer.
321
//-----------------------------------------------------------------------------
322
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
323
0
{
324
0
  if ( nDecodeDestLen < nEncodedSourceLen )
325
0
  {
326
0
    //AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
327
0
    return 0;
328
0
  }
329
0
330
0
  int iDestPos = 0;
331
0
  for( int i=0; i < nEncodedSourceLen; ++i )
332
0
  {
333
0
    if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
334
0
    {
335
0
      pchDecodeDest[ iDestPos++ ] = ' ';
336
0
    }
337
0
    else if ( pchEncodedSource[i] == '%' )
338
0
    {
339
0
      // Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
340
0
341
0
      // First make sure we have 2 more chars
342
0
      if ( i < nEncodedSourceLen - 2 )
343
0
      {
344
0
        char cHexDigit1 = pchEncodedSource[i+1];
345
0
        char cHexDigit2 = pchEncodedSource[i+2];
346
0
347
0
        // Turn the chars into a hex value, if they are not valid, then we'll
348
0
        // just place the % and the following two chars direct into the string,
349
0
        // even though this really shouldn't happen, who knows what bad clients
350
0
        // may do with encoding.
351
0
        bool bValid = false;
352
0
        int iValue = iHexCharToInt( cHexDigit1 );
353
0
        if ( iValue != -1 )
354
0
        {
355
0
          iValue *= 16;
356
0
          int iValue2 = iHexCharToInt( cHexDigit2 );
357
0
          if ( iValue2 != -1 )
358
0
          {
359
0
            iValue += iValue2;
360
0
            pchDecodeDest[ iDestPos++ ] = (char)iValue;
361
0
            bValid = true;
362
0
          }
363
0
        }
364
0
365
0
        if ( !bValid )
366
0
        {
367
0
          pchDecodeDest[ iDestPos++ ] = '%';
368
0
          pchDecodeDest[ iDestPos++ ] = cHexDigit1;
369
0
          pchDecodeDest[ iDestPos++ ] = cHexDigit2;
370
0
        }
371
0
      }
372
0
373
0
      // Skip ahead
374
0
      i += 2;
375
0
    }
376
0
    else
377
0
    {
378
0
      pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
379
0
    }
380
0
  }
381
0
382
0
  // We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
383
0
  // go ahead and do it as this can avoid bugs.
384
0
  if ( iDestPos < nDecodeDestLen )
385
0
  {
386
0
    pchDecodeDest[iDestPos] = 0;
387
0
  }
388
0
389
0
  return (size_t)iDestPos;
390
0
}
391
392
//-----------------------------------------------------------------------------
393
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
394
//          This version of the call isn't a strict RFC implementation, but uses + for space as is
395
//          the standard in HTML form encoding, despite it not being part of the RFC.
396
//
397
//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
398
//-----------------------------------------------------------------------------
399
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
400
0
{
401
0
  return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
402
0
}
403
404
405
//-----------------------------------------------------------------------------
406
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
407
//          This version of the call isn't a strict RFC implementation, but uses + for space as is
408
//          the standard in HTML form encoding, despite it not being part of the RFC.
409
//
410
//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
411
//      Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
412
//-----------------------------------------------------------------------------
413
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
414
0
{
415
0
  return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
416
0
}
417
418
//-----------------------------------------------------------------------------
419
void V_StripExtension( std::string &in )
420
0
{
421
0
  // Find the last dot. If it's followed by a dot or a slash, then it's part of a 
422
0
  // directory specifier like ../../somedir/./blah.
423
0
  std::string::size_type test = in.rfind( '.' );
424
0
  if ( test != std::string::npos )
425
0
  {
426
0
    // This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
427
0
    // Which would otherwise wind up with "" and "c:\my@email", respectively.
428
0
    if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
429
0
    {
430
0
      in.resize( test );
431
0
    }
432
0
  }
433
0
}
434
435
436
//-----------------------------------------------------------------------------
437
// Purpose: Tokenizes a string into a vector of strings
438
//-----------------------------------------------------------------------------
439
std::vector<std::string> TokenizeString( const std::string & sString, char cToken )
440
0
{
441
0
  std::vector<std::string> vecStrings;
442
0
  std::istringstream stream( sString );
443
0
  std::string s;
444
0
  while ( std::getline( stream, s, cToken ) )
445
0
  {
446
0
    vecStrings.push_back( s );
447
0
  }
448
0
  return vecStrings;
449
0
}
450