LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/base - stringencode.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 399 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/base/stringencode.h"
      12             : 
      13             : #include <stdio.h>
      14             : #include <stdlib.h>
      15             : 
      16             : #include "webrtc/base/checks.h"
      17             : #include "webrtc/base/stringutils.h"
      18             : 
      19             : namespace rtc {
      20             : 
      21             : /////////////////////////////////////////////////////////////////////////////
      22             : // String Encoding Utilities
      23             : /////////////////////////////////////////////////////////////////////////////
      24             : 
      25           0 : size_t escape(char * buffer, size_t buflen,
      26             :               const char * source, size_t srclen,
      27             :               const char * illegal, char escape) {
      28           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
      29           0 :   if (buflen <= 0)
      30           0 :     return 0;
      31             : 
      32           0 :   size_t srcpos = 0, bufpos = 0;
      33           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
      34           0 :     char ch = source[srcpos++];
      35           0 :     if ((ch == escape) || ::strchr(illegal, ch)) {
      36           0 :       if (bufpos + 2 >= buflen)
      37           0 :         break;
      38           0 :       buffer[bufpos++] = escape;
      39             :     }
      40           0 :     buffer[bufpos++] = ch;
      41             :   }
      42             : 
      43           0 :   buffer[bufpos] = '\0';
      44           0 :   return bufpos;
      45             : }
      46             : 
      47           0 : size_t unescape(char * buffer, size_t buflen,
      48             :                 const char * source, size_t srclen,
      49             :                 char escape) {
      50           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
      51           0 :   if (buflen <= 0)
      52           0 :     return 0;
      53             : 
      54           0 :   size_t srcpos = 0, bufpos = 0;
      55           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
      56           0 :     char ch = source[srcpos++];
      57           0 :     if ((ch == escape) && (srcpos < srclen)) {
      58           0 :       ch = source[srcpos++];
      59             :     }
      60           0 :     buffer[bufpos++] = ch;
      61             :   }
      62           0 :   buffer[bufpos] = '\0';
      63           0 :   return bufpos;
      64             : }
      65             : 
      66           0 : size_t encode(char * buffer, size_t buflen,
      67             :               const char * source, size_t srclen,
      68             :               const char * illegal, char escape) {
      69           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
      70           0 :   if (buflen <= 0)
      71           0 :     return 0;
      72             : 
      73           0 :   size_t srcpos = 0, bufpos = 0;
      74           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
      75           0 :     char ch = source[srcpos++];
      76           0 :     if ((ch != escape) && !::strchr(illegal, ch)) {
      77           0 :       buffer[bufpos++] = ch;
      78           0 :     } else if (bufpos + 3 >= buflen) {
      79           0 :       break;
      80             :     } else {
      81           0 :       buffer[bufpos+0] = escape;
      82           0 :       buffer[bufpos+1] = hex_encode((static_cast<unsigned char>(ch) >> 4) & 0xF);
      83           0 :       buffer[bufpos+2] = hex_encode((static_cast<unsigned char>(ch)     ) & 0xF);
      84           0 :       bufpos += 3;
      85             :     }
      86             :   }
      87           0 :   buffer[bufpos] = '\0';
      88           0 :   return bufpos;
      89             : }
      90             : 
      91           0 : size_t decode(char * buffer, size_t buflen,
      92             :               const char * source, size_t srclen,
      93             :               char escape) {
      94           0 :   if (buflen <= 0)
      95           0 :     return 0;
      96             : 
      97             :   unsigned char h1, h2;
      98           0 :   size_t srcpos = 0, bufpos = 0;
      99           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     100           0 :     char ch = source[srcpos++];
     101           0 :     if ((ch == escape)
     102           0 :         && (srcpos + 1 < srclen)
     103           0 :         && hex_decode(source[srcpos], &h1)
     104           0 :         && hex_decode(source[srcpos+1], &h2)) {
     105           0 :       buffer[bufpos++] = (h1 << 4) | h2;
     106           0 :       srcpos += 2;
     107             :     } else {
     108           0 :       buffer[bufpos++] = ch;
     109             :     }
     110             :   }
     111           0 :   buffer[bufpos] = '\0';
     112           0 :   return bufpos;
     113             : }
     114             : 
     115           0 : const char* unsafe_filename_characters() {
     116             :   // It might be better to have a single specification which is the union of
     117             :   // all operating systems, unless one system is overly restrictive.
     118             : #if defined(WEBRTC_WIN)
     119             :   return "\\/:*?\"<>|";
     120             : #else  // !WEBRTC_WIN
     121             :   // TODO(grunell): Should this never be reached?
     122           0 :   RTC_NOTREACHED();
     123           0 :   return "";
     124             : #endif  // !WEBRTC_WIN
     125             : }
     126             : 
     127             : const unsigned char URL_UNSAFE  = 0x1; // 0-33 "#$%&+,/:;<=>?@[\]^`{|} 127
     128             : const unsigned char XML_UNSAFE  = 0x2; // "&'<>
     129             : const unsigned char HTML_UNSAFE = 0x2; // "&'<>
     130             : 
     131             : //  ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 6 5 7 8 9 : ; < = > ?
     132             : //@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
     133             : //` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
     134             : 
     135             : const unsigned char ASCII_CLASS[128] = {
     136             :   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
     137             :   1,0,3,1,1,1,3,2,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,3,1,3,1,
     138             :   1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,
     139             :   1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,
     140             : };
     141             : 
     142           0 : size_t url_encode(char * buffer, size_t buflen,
     143             :                   const char * source, size_t srclen) {
     144           0 :   if (NULL == buffer)
     145           0 :     return srclen * 3 + 1;
     146           0 :   if (buflen <= 0)
     147           0 :     return 0;
     148             : 
     149           0 :   size_t srcpos = 0, bufpos = 0;
     150           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     151           0 :     unsigned char ch = source[srcpos++];
     152           0 :     if ((ch < 128) && (ASCII_CLASS[ch] & URL_UNSAFE)) {
     153           0 :       if (bufpos + 3 >= buflen) {
     154           0 :         break;
     155             :       }
     156           0 :       buffer[bufpos+0] = '%';
     157           0 :       buffer[bufpos+1] = hex_encode((ch >> 4) & 0xF);
     158           0 :       buffer[bufpos+2] = hex_encode((ch     ) & 0xF);
     159           0 :       bufpos += 3;
     160             :     } else {
     161           0 :       buffer[bufpos++] = ch;
     162             :     }
     163             :   }
     164           0 :   buffer[bufpos] = '\0';
     165           0 :   return bufpos;
     166             : }
     167             : 
     168           0 : size_t url_decode(char * buffer, size_t buflen,
     169             :                   const char * source, size_t srclen) {
     170           0 :   if (NULL == buffer)
     171           0 :     return srclen + 1;
     172           0 :   if (buflen <= 0)
     173           0 :     return 0;
     174             : 
     175             :   unsigned char h1, h2;
     176           0 :   size_t srcpos = 0, bufpos = 0;
     177           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     178           0 :     unsigned char ch = source[srcpos++];
     179           0 :     if (ch == '+') {
     180           0 :       buffer[bufpos++] = ' ';
     181           0 :     } else if ((ch == '%')
     182           0 :                && (srcpos + 1 < srclen)
     183           0 :                && hex_decode(source[srcpos], &h1)
     184           0 :                && hex_decode(source[srcpos+1], &h2))
     185             :     {
     186           0 :       buffer[bufpos++] = (h1 << 4) | h2;
     187           0 :       srcpos += 2;
     188             :     } else {
     189           0 :       buffer[bufpos++] = ch;
     190             :     }
     191             :   }
     192           0 :   buffer[bufpos] = '\0';
     193           0 :   return bufpos;
     194             : }
     195             : 
     196           0 : size_t utf8_decode(const char* source, size_t srclen, unsigned long* value) {
     197           0 :   const unsigned char* s = reinterpret_cast<const unsigned char*>(source);
     198           0 :   if ((s[0] & 0x80) == 0x00) {                    // Check s[0] == 0xxxxxxx
     199           0 :     *value = s[0];
     200           0 :     return 1;
     201             :   }
     202           0 :   if ((srclen < 2) || ((s[1] & 0xC0) != 0x80)) {  // Check s[1] != 10xxxxxx
     203           0 :     return 0;
     204             :   }
     205             :   // Accumulate the trailer byte values in value16, and combine it with the
     206             :   // relevant bits from s[0], once we've determined the sequence length.
     207           0 :   unsigned long value16 = (s[1] & 0x3F);
     208           0 :   if ((s[0] & 0xE0) == 0xC0) {                    // Check s[0] == 110xxxxx
     209           0 :     *value = ((s[0] & 0x1F) << 6) | value16;
     210           0 :     return 2;
     211             :   }
     212           0 :   if ((srclen < 3) || ((s[2] & 0xC0) != 0x80)) {  // Check s[2] != 10xxxxxx
     213           0 :     return 0;
     214             :   }
     215           0 :   value16 = (value16 << 6) | (s[2] & 0x3F);
     216           0 :   if ((s[0] & 0xF0) == 0xE0) {                    // Check s[0] == 1110xxxx
     217           0 :     *value = ((s[0] & 0x0F) << 12) | value16;
     218           0 :     return 3;
     219             :   }
     220           0 :   if ((srclen < 4) || ((s[3] & 0xC0) != 0x80)) {  // Check s[3] != 10xxxxxx
     221           0 :     return 0;
     222             :   }
     223           0 :   value16 = (value16 << 6) | (s[3] & 0x3F);
     224           0 :   if ((s[0] & 0xF8) == 0xF0) {                    // Check s[0] == 11110xxx
     225           0 :     *value = ((s[0] & 0x07) << 18) | value16;
     226           0 :     return 4;
     227             :   }
     228           0 :   return 0;
     229             : }
     230             : 
     231           0 : size_t utf8_encode(char* buffer, size_t buflen, unsigned long value) {
     232           0 :   if ((value <= 0x7F) && (buflen >= 1)) {
     233           0 :     buffer[0] = static_cast<unsigned char>(value);
     234           0 :     return 1;
     235             :   }
     236           0 :   if ((value <= 0x7FF) && (buflen >= 2)) {
     237           0 :     buffer[0] = 0xC0 | static_cast<unsigned char>(value >> 6);
     238           0 :     buffer[1] = 0x80 | static_cast<unsigned char>(value & 0x3F);
     239           0 :     return 2;
     240             :   }
     241           0 :   if ((value <= 0xFFFF) && (buflen >= 3)) {
     242           0 :     buffer[0] = 0xE0 | static_cast<unsigned char>(value >> 12);
     243           0 :     buffer[1] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
     244           0 :     buffer[2] = 0x80 | static_cast<unsigned char>(value & 0x3F);
     245           0 :     return 3;
     246             :   }
     247           0 :   if ((value <= 0x1FFFFF) && (buflen >= 4)) {
     248           0 :     buffer[0] = 0xF0 | static_cast<unsigned char>(value >> 18);
     249           0 :     buffer[1] = 0x80 | static_cast<unsigned char>((value >> 12) & 0x3F);
     250           0 :     buffer[2] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
     251           0 :     buffer[3] = 0x80 | static_cast<unsigned char>(value & 0x3F);
     252           0 :     return 4;
     253             :   }
     254           0 :   return 0;
     255             : }
     256             : 
     257           0 : size_t html_encode(char * buffer, size_t buflen,
     258             :                    const char * source, size_t srclen) {
     259           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
     260           0 :   if (buflen <= 0)
     261           0 :     return 0;
     262             : 
     263           0 :   size_t srcpos = 0, bufpos = 0;
     264           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     265           0 :     unsigned char ch = source[srcpos];
     266           0 :     if (ch < 128) {
     267           0 :       srcpos += 1;
     268           0 :       if (ASCII_CLASS[ch] & HTML_UNSAFE) {
     269           0 :         const char * escseq = 0;
     270           0 :         size_t esclen = 0;
     271           0 :         switch (ch) {
     272           0 :           case '<':  escseq = "&lt;";   esclen = 4; break;
     273           0 :           case '>':  escseq = "&gt;";   esclen = 4; break;
     274           0 :           case '\'': escseq = "&#39;";  esclen = 5; break;
     275           0 :           case '\"': escseq = "&quot;"; esclen = 6; break;
     276           0 :           case '&':  escseq = "&amp;";  esclen = 5; break;
     277           0 :           default: RTC_NOTREACHED();
     278             :         }
     279           0 :         if (bufpos + esclen >= buflen) {
     280           0 :           break;
     281             :         }
     282           0 :         memcpy(buffer + bufpos, escseq, esclen);
     283           0 :         bufpos += esclen;
     284             :       } else {
     285           0 :         buffer[bufpos++] = ch;
     286             :       }
     287             :     } else {
     288             :       // Largest value is 0x1FFFFF => &#2097151;  (10 characters)
     289           0 :       const size_t kEscseqSize = 11;
     290             :       char escseq[kEscseqSize];
     291             :       unsigned long val;
     292           0 :       if (size_t vallen = utf8_decode(&source[srcpos], srclen - srcpos, &val)) {
     293           0 :         srcpos += vallen;
     294             :       } else {
     295             :         // Not a valid utf8 sequence, just use the raw character.
     296           0 :         val = static_cast<unsigned char>(source[srcpos++]);
     297             :       }
     298           0 :       size_t esclen = sprintfn(escseq, kEscseqSize, "&#%lu;", val);
     299           0 :       if (bufpos + esclen >= buflen) {
     300           0 :         break;
     301             :       }
     302           0 :       memcpy(buffer + bufpos, escseq, esclen);
     303           0 :       bufpos += esclen;
     304             :     }
     305             :   }
     306           0 :   buffer[bufpos] = '\0';
     307           0 :   return bufpos;
     308             : }
     309             : 
     310           0 : size_t html_decode(char * buffer, size_t buflen,
     311             :                    const char * source, size_t srclen) {
     312           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
     313           0 :   return xml_decode(buffer, buflen, source, srclen);
     314             : }
     315             : 
     316           0 : size_t xml_encode(char * buffer, size_t buflen,
     317             :                   const char * source, size_t srclen) {
     318           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
     319           0 :   if (buflen <= 0)
     320           0 :     return 0;
     321             : 
     322           0 :   size_t srcpos = 0, bufpos = 0;
     323           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     324           0 :     unsigned char ch = source[srcpos++];
     325           0 :     if ((ch < 128) && (ASCII_CLASS[ch] & XML_UNSAFE)) {
     326           0 :       const char * escseq = 0;
     327           0 :       size_t esclen = 0;
     328           0 :       switch (ch) {
     329           0 :         case '<':  escseq = "&lt;";   esclen = 4; break;
     330           0 :         case '>':  escseq = "&gt;";   esclen = 4; break;
     331           0 :         case '\'': escseq = "&apos;"; esclen = 6; break;
     332           0 :         case '\"': escseq = "&quot;"; esclen = 6; break;
     333           0 :         case '&':  escseq = "&amp;";  esclen = 5; break;
     334           0 :         default: RTC_NOTREACHED();
     335             :       }
     336           0 :       if (bufpos + esclen >= buflen) {
     337           0 :         break;
     338             :       }
     339           0 :       memcpy(buffer + bufpos, escseq, esclen);
     340           0 :       bufpos += esclen;
     341             :     } else {
     342           0 :       buffer[bufpos++] = ch;
     343             :     }
     344             :   }
     345           0 :   buffer[bufpos] = '\0';
     346           0 :   return bufpos;
     347             : }
     348             : 
     349           0 : size_t xml_decode(char * buffer, size_t buflen,
     350             :                   const char * source, size_t srclen) {
     351           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
     352           0 :   if (buflen <= 0)
     353           0 :     return 0;
     354             : 
     355           0 :   size_t srcpos = 0, bufpos = 0;
     356           0 :   while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
     357           0 :     unsigned char ch = source[srcpos++];
     358           0 :     if (ch != '&') {
     359           0 :       buffer[bufpos++] = ch;
     360           0 :     } else if ((srcpos + 2 < srclen)
     361           0 :                && (memcmp(source + srcpos, "lt;", 3) == 0)) {
     362           0 :       buffer[bufpos++] = '<';
     363           0 :       srcpos += 3;
     364           0 :     } else if ((srcpos + 2 < srclen)
     365           0 :                && (memcmp(source + srcpos, "gt;", 3) == 0)) {
     366           0 :       buffer[bufpos++] = '>';
     367           0 :       srcpos += 3;
     368           0 :     } else if ((srcpos + 4 < srclen)
     369           0 :                && (memcmp(source + srcpos, "apos;", 5) == 0)) {
     370           0 :       buffer[bufpos++] = '\'';
     371           0 :       srcpos += 5;
     372           0 :     } else if ((srcpos + 4 < srclen)
     373           0 :                && (memcmp(source + srcpos, "quot;", 5) == 0)) {
     374           0 :       buffer[bufpos++] = '\"';
     375           0 :       srcpos += 5;
     376           0 :     } else if ((srcpos + 3 < srclen)
     377           0 :                && (memcmp(source + srcpos, "amp;", 4) == 0)) {
     378           0 :       buffer[bufpos++] = '&';
     379           0 :       srcpos += 4;
     380           0 :     } else if ((srcpos < srclen) && (source[srcpos] == '#')) {
     381           0 :       int int_base = 10;
     382           0 :       if ((srcpos + 1 < srclen) && (source[srcpos+1] == 'x')) {
     383           0 :         int_base = 16;
     384           0 :         srcpos += 1;
     385             :       }
     386             :       char * ptr;
     387             :       // TODO(grunell): Fix hack (ptr may go past end of data)
     388           0 :       unsigned long val = strtoul(source + srcpos + 1, &ptr, int_base);
     389           0 :       if ((static_cast<size_t>(ptr - source) < srclen) && (*ptr == ';')) {
     390           0 :         srcpos = ptr - source + 1;
     391             :       } else {
     392             :         // Not a valid escape sequence.
     393             :         break;
     394             :       }
     395           0 :       if (size_t esclen = utf8_encode(buffer + bufpos, buflen - bufpos, val)) {
     396           0 :         bufpos += esclen;
     397             :       } else {
     398             :         // Not enough room to encode the character, or illegal character
     399           0 :         break;
     400             :       }
     401             :     } else {
     402             :       // Unrecognized escape sequence.
     403             :       break;
     404             :     }
     405             :   }
     406           0 :   buffer[bufpos] = '\0';
     407           0 :   return bufpos;
     408             : }
     409             : 
     410             : static const char HEX[] = "0123456789abcdef";
     411             : 
     412           0 : char hex_encode(unsigned char val) {
     413           0 :   RTC_DCHECK_LT(val, 16);
     414           0 :   return (val < 16) ? HEX[val] : '!';
     415             : }
     416             : 
     417           0 : bool hex_decode(char ch, unsigned char* val) {
     418           0 :   if ((ch >= '0') && (ch <= '9')) {
     419           0 :     *val = ch - '0';
     420           0 :   } else if ((ch >= 'A') && (ch <= 'Z')) {
     421           0 :     *val = (ch - 'A') + 10;
     422           0 :   } else if ((ch >= 'a') && (ch <= 'z')) {
     423           0 :     *val = (ch - 'a') + 10;
     424             :   } else {
     425           0 :     return false;
     426             :   }
     427           0 :   return true;
     428             : }
     429             : 
     430           0 : size_t hex_encode(char* buffer, size_t buflen,
     431             :                   const char* csource, size_t srclen) {
     432           0 :   return hex_encode_with_delimiter(buffer, buflen, csource, srclen, 0);
     433             : }
     434             : 
     435           0 : size_t hex_encode_with_delimiter(char* buffer, size_t buflen,
     436             :                                  const char* csource, size_t srclen,
     437             :                                  char delimiter) {
     438           0 :   RTC_DCHECK(buffer);  // TODO(grunell): estimate output size
     439           0 :   if (buflen == 0)
     440           0 :     return 0;
     441             : 
     442             :   // Init and check bounds.
     443             :   const unsigned char* bsource =
     444           0 :       reinterpret_cast<const unsigned char*>(csource);
     445           0 :   size_t srcpos = 0, bufpos = 0;
     446           0 :   size_t needed = delimiter ? (srclen * 3) : (srclen * 2 + 1);
     447           0 :   if (buflen < needed)
     448           0 :     return 0;
     449             : 
     450           0 :   while (srcpos < srclen) {
     451           0 :     unsigned char ch = bsource[srcpos++];
     452           0 :     buffer[bufpos  ] = hex_encode((ch >> 4) & 0xF);
     453           0 :     buffer[bufpos+1] = hex_encode((ch     ) & 0xF);
     454           0 :     bufpos += 2;
     455             : 
     456             :     // Don't write a delimiter after the last byte.
     457           0 :     if (delimiter && (srcpos < srclen)) {
     458           0 :       buffer[bufpos] = delimiter;
     459           0 :       ++bufpos;
     460             :     }
     461             :   }
     462             : 
     463             :   // Null terminate.
     464           0 :   buffer[bufpos] = '\0';
     465           0 :   return bufpos;
     466             : }
     467             : 
     468           0 : std::string hex_encode(const std::string& str) {
     469           0 :   return hex_encode(str.c_str(), str.size());
     470             : }
     471             : 
     472           0 : std::string hex_encode(const char* source, size_t srclen) {
     473           0 :   return hex_encode_with_delimiter(source, srclen, 0);
     474             : }
     475             : 
     476           0 : std::string hex_encode_with_delimiter(const char* source, size_t srclen,
     477             :                                       char delimiter) {
     478           0 :   const size_t kBufferSize = srclen * 3;
     479           0 :   char* buffer = STACK_ARRAY(char, kBufferSize);
     480           0 :   size_t length = hex_encode_with_delimiter(buffer, kBufferSize,
     481           0 :                                             source, srclen, delimiter);
     482           0 :   RTC_DCHECK(srclen == 0 || length > 0);
     483           0 :   return std::string(buffer, length);
     484             : }
     485             : 
     486           0 : size_t hex_decode(char * cbuffer, size_t buflen,
     487             :                   const char * source, size_t srclen) {
     488           0 :   return hex_decode_with_delimiter(cbuffer, buflen, source, srclen, 0);
     489             : }
     490             : 
     491           0 : size_t hex_decode_with_delimiter(char* cbuffer, size_t buflen,
     492             :                                  const char* source, size_t srclen,
     493             :                                  char delimiter) {
     494           0 :   RTC_DCHECK(cbuffer);  // TODO(grunell): estimate output size
     495           0 :   if (buflen == 0)
     496           0 :     return 0;
     497             : 
     498             :   // Init and bounds check.
     499           0 :   unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer);
     500           0 :   size_t srcpos = 0, bufpos = 0;
     501           0 :   size_t needed = (delimiter) ? (srclen + 1) / 3 : srclen / 2;
     502           0 :   if (buflen < needed)
     503           0 :     return 0;
     504             : 
     505           0 :   while (srcpos < srclen) {
     506           0 :     if ((srclen - srcpos) < 2) {
     507             :       // This means we have an odd number of bytes.
     508           0 :       return 0;
     509             :     }
     510             : 
     511             :     unsigned char h1, h2;
     512           0 :     if (!hex_decode(source[srcpos], &h1) ||
     513           0 :         !hex_decode(source[srcpos + 1], &h2))
     514           0 :       return 0;
     515             : 
     516           0 :     bbuffer[bufpos++] = (h1 << 4) | h2;
     517           0 :     srcpos += 2;
     518             : 
     519             :     // Remove the delimiter if needed.
     520           0 :     if (delimiter && (srclen - srcpos) > 1) {
     521           0 :       if (source[srcpos] != delimiter)
     522           0 :         return 0;
     523           0 :       ++srcpos;
     524             :     }
     525             :   }
     526             : 
     527           0 :   return bufpos;
     528             : }
     529             : 
     530           0 : size_t hex_decode(char* buffer, size_t buflen, const std::string& source) {
     531           0 :   return hex_decode_with_delimiter(buffer, buflen, source, 0);
     532             : }
     533           0 : size_t hex_decode_with_delimiter(char* buffer, size_t buflen,
     534             :                                  const std::string& source, char delimiter) {
     535           0 :   return hex_decode_with_delimiter(buffer, buflen,
     536           0 :                                    source.c_str(), source.length(), delimiter);
     537             : }
     538             : 
     539           0 : size_t transform(std::string& value, size_t maxlen, const std::string& source,
     540             :                  Transform t) {
     541           0 :   char* buffer = STACK_ARRAY(char, maxlen + 1);
     542           0 :   size_t length = t(buffer, maxlen + 1, source.data(), source.length());
     543           0 :   value.assign(buffer, length);
     544           0 :   return length;
     545             : }
     546             : 
     547           0 : std::string s_transform(const std::string& source, Transform t) {
     548             :   // Ask transformation function to approximate the destination size (returns upper bound)
     549           0 :   size_t maxlen = t(NULL, 0, source.data(), source.length());
     550           0 :   char * buffer = STACK_ARRAY(char, maxlen);
     551           0 :   size_t len = t(buffer, maxlen, source.data(), source.length());
     552           0 :   std::string result(buffer, len);
     553           0 :   return result;
     554             : }
     555             : 
     556           0 : size_t tokenize(const std::string& source, char delimiter,
     557             :                 std::vector<std::string>* fields) {
     558           0 :   fields->clear();
     559           0 :   size_t last = 0;
     560           0 :   for (size_t i = 0; i < source.length(); ++i) {
     561           0 :     if (source[i] == delimiter) {
     562           0 :       if (i != last) {
     563           0 :         fields->push_back(source.substr(last, i - last));
     564             :       }
     565           0 :       last = i + 1;
     566             :     }
     567             :   }
     568           0 :   if (last != source.length()) {
     569           0 :     fields->push_back(source.substr(last, source.length() - last));
     570             :   }
     571           0 :   return fields->size();
     572             : }
     573             : 
     574           0 : size_t tokenize_with_empty_tokens(const std::string& source,
     575             :                                   char delimiter,
     576             :                                   std::vector<std::string>* fields) {
     577           0 :   fields->clear();
     578           0 :   size_t last = 0;
     579           0 :   for (size_t i = 0; i < source.length(); ++i) {
     580           0 :     if (source[i] == delimiter) {
     581           0 :       fields->push_back(source.substr(last, i - last));
     582           0 :       last = i + 1;
     583             :     }
     584             :   }
     585           0 :   fields->push_back(source.substr(last, source.length() - last));
     586           0 :   return fields->size();
     587             : }
     588             : 
     589           0 : size_t tokenize_append(const std::string& source, char delimiter,
     590             :                        std::vector<std::string>* fields) {
     591           0 :   if (!fields) return 0;
     592             : 
     593           0 :   std::vector<std::string> new_fields;
     594           0 :   tokenize(source, delimiter, &new_fields);
     595           0 :   fields->insert(fields->end(), new_fields.begin(), new_fields.end());
     596           0 :   return fields->size();
     597             : }
     598             : 
     599           0 : size_t tokenize(const std::string& source, char delimiter, char start_mark,
     600             :                 char end_mark, std::vector<std::string>* fields) {
     601           0 :   if (!fields) return 0;
     602           0 :   fields->clear();
     603             : 
     604           0 :   std::string remain_source = source;
     605           0 :   while (!remain_source.empty()) {
     606           0 :     size_t start_pos = remain_source.find(start_mark);
     607           0 :     if (std::string::npos == start_pos) break;
     608           0 :     std::string pre_mark;
     609           0 :     if (start_pos > 0) {
     610           0 :       pre_mark = remain_source.substr(0, start_pos - 1);
     611             :     }
     612             : 
     613           0 :     ++start_pos;
     614           0 :     size_t end_pos = remain_source.find(end_mark, start_pos);
     615           0 :     if (std::string::npos == end_pos) break;
     616             : 
     617             :     // We have found the matching marks. First tokenize the pre-mask. Then add
     618             :     // the marked part as a single field. Finally, loop back for the post-mark.
     619           0 :     tokenize_append(pre_mark, delimiter, fields);
     620           0 :     fields->push_back(remain_source.substr(start_pos, end_pos - start_pos));
     621           0 :     remain_source = remain_source.substr(end_pos + 1);
     622             :   }
     623             : 
     624           0 :   return tokenize_append(remain_source, delimiter, fields);
     625             : }
     626             : 
     627           0 : bool tokenize_first(const std::string& source,
     628             :                     const char delimiter,
     629             :                     std::string* token,
     630             :                     std::string* rest) {
     631             :   // Find the first delimiter
     632           0 :   size_t left_pos = source.find(delimiter);
     633           0 :   if (left_pos == std::string::npos) {
     634           0 :     return false;
     635             :   }
     636             : 
     637             :   // Look for additional occurrances of delimiter.
     638           0 :   size_t right_pos = left_pos + 1;
     639           0 :   while (source[right_pos] == delimiter) {
     640           0 :     right_pos++;
     641             :   }
     642             : 
     643           0 :   *token = source.substr(0, left_pos);
     644           0 :   *rest = source.substr(right_pos);
     645           0 :   return true;
     646             : }
     647             : 
     648           0 : size_t split(const std::string& source, char delimiter,
     649             :              std::vector<std::string>* fields) {
     650           0 :   RTC_DCHECK(fields);
     651           0 :   fields->clear();
     652           0 :   size_t last = 0;
     653           0 :   for (size_t i = 0; i < source.length(); ++i) {
     654           0 :     if (source[i] == delimiter) {
     655           0 :       fields->push_back(source.substr(last, i - last));
     656           0 :       last = i + 1;
     657             :     }
     658             :   }
     659           0 :   fields->push_back(source.substr(last, source.length() - last));
     660           0 :   return fields->size();
     661             : }
     662             : 
     663           0 : char make_char_safe_for_filename(char c) {
     664           0 :   if (c < 32)
     665           0 :     return '_';
     666             : 
     667           0 :   switch (c) {
     668             :     case '<':
     669             :     case '>':
     670             :     case ':':
     671             :     case '"':
     672             :     case '/':
     673             :     case '\\':
     674             :     case '|':
     675             :     case '*':
     676             :     case '?':
     677           0 :       return '_';
     678             : 
     679             :     default:
     680           0 :       return c;
     681             :   }
     682             : }
     683             : 
     684             : /*
     685             : void sprintf(std::string& value, size_t maxlen, const char * format, ...) {
     686             :   char * buffer = STACK_ARRAY(char, maxlen + 1);
     687             :   va_list args;
     688             :   va_start(args, format);
     689             :   value.assign(buffer, vsprintfn(buffer, maxlen + 1, format, args));
     690             :   va_end(args);
     691             : }
     692             : */
     693             : 
     694             : /////////////////////////////////////////////////////////////////////////////
     695             : 
     696             : }  // namespace rtc

Generated by: LCOV version 1.13