147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringencode.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <stdio.h>
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <stdlib.h>
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/basictypes.h"
174dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#include "webrtc/base/checks.h"
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringutils.h"
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// String Encoding Utilities
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t escape(char * buffer, size_t buflen,
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              const char * source, size_t srclen,
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              const char * illegal, char escape) {
294dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch = source[srcpos++];
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch == escape) || ::strchr(illegal, ch)) {
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (bufpos + 2 >= buflen)
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = escape;
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[bufpos++] = ch;
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t unescape(char * buffer, size_t buflen,
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                const char * source, size_t srclen,
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                char escape) {
514dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch = source[srcpos++];
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch == escape) && (srcpos < srclen)) {
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ch = source[srcpos++];
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[bufpos++] = ch;
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t encode(char * buffer, size_t buflen,
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              const char * source, size_t srclen,
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              const char * illegal, char escape) {
704dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch = source[srcpos++];
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch != escape) && !::strchr(illegal, ch)) {
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (bufpos + 3 >= buflen) {
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+0] = escape;
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+1] = hex_encode((static_cast<unsigned char>(ch) >> 4) & 0xF);
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+2] = hex_encode((static_cast<unsigned char>(ch)     ) & 0xF);
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bufpos += 3;
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t decode(char * buffer, size_t buflen,
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              const char * source, size_t srclen,
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              char escape) {
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  unsigned char h1, h2;
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch = source[srcpos++];
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch == escape)
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        && (srcpos + 1 < srclen)
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        && hex_decode(source[srcpos], &h1)
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        && hex_decode(source[srcpos+1], &h2)) {
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = (h1 << 4) | h2;
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 2;
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst char* unsafe_filename_characters() {
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // It might be better to have a single specification which is the union of
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // all operating systems, unless one system is overly restrictive.
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return "\\/:*?\"<>|";
1214dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#else  // !WEBRTC_WIN
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO
1234dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(false);
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return "";
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // !WEBRTC_WIN
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst unsigned char URL_UNSAFE  = 0x1; // 0-33 "#$%&+,/:;<=>?@[\]^`{|} 127
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst unsigned char XML_UNSAFE  = 0x2; // "&'<>
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst unsigned char HTML_UNSAFE = 0x2; // "&'<>
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//  ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 6 5 7 8 9 : ; < = > ?
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//@ 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 [ \ ] ^ _
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//` 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 { | } ~
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst unsigned char ASCII_CLASS[128] = {
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  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,
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  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,
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  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,
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  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,
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t url_encode(char * buffer, size_t buflen,
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char * source, size_t srclen) {
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (NULL == buffer)
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return srclen * 3 + 1;
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = source[srcpos++];
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch < 128) && (ASCII_CLASS[ch] & URL_UNSAFE)) {
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (bufpos + 3 >= buflen) {
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+0] = '%';
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+1] = hex_encode((ch >> 4) & 0xF);
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos+2] = hex_encode((ch     ) & 0xF);
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bufpos += 3;
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t url_decode(char * buffer, size_t buflen,
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char * source, size_t srclen) {
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (NULL == buffer)
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return srclen + 1;
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  unsigned char h1, h2;
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = source[srcpos++];
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ch == '+') {
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ' ';
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((ch == '%')
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (srcpos + 1 < srclen)
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && hex_decode(source[srcpos], &h1)
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && hex_decode(source[srcpos+1], &h2))
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    {
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = (h1 << 4) | h2;
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 2;
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t utf8_decode(const char* source, size_t srclen, unsigned long* value) {
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const unsigned char* s = reinterpret_cast<const unsigned char*>(source);
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((s[0] & 0x80) == 0x00) {                    // Check s[0] == 0xxxxxxx
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *value = s[0];
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 1;
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((srclen < 2) || ((s[1] & 0xC0) != 0x80)) {  // Check s[1] != 10xxxxxx
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Accumulate the trailer byte values in value16, and combine it with the
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // relevant bits from s[0], once we've determined the sequence length.
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  unsigned long value16 = (s[1] & 0x3F);
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((s[0] & 0xE0) == 0xC0) {                    // Check s[0] == 110xxxxx
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *value = ((s[0] & 0x1F) << 6) | value16;
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 2;
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((srclen < 3) || ((s[2] & 0xC0) != 0x80)) {  // Check s[2] != 10xxxxxx
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  value16 = (value16 << 6) | (s[2] & 0x3F);
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((s[0] & 0xF0) == 0xE0) {                    // Check s[0] == 1110xxxx
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *value = ((s[0] & 0x0F) << 12) | value16;
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 3;
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((srclen < 4) || ((s[3] & 0xC0) != 0x80)) {  // Check s[3] != 10xxxxxx
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  value16 = (value16 << 6) | (s[3] & 0x3F);
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((s[0] & 0xF8) == 0xF0) {                    // Check s[0] == 11110xxx
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *value = ((s[0] & 0x07) << 18) | value16;
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 4;
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t utf8_encode(char* buffer, size_t buflen, unsigned long value) {
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((value <= 0x7F) && (buflen >= 1)) {
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[0] = static_cast<unsigned char>(value);
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 1;
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((value <= 0x7FF) && (buflen >= 2)) {
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[0] = 0xC0 | static_cast<unsigned char>(value >> 6);
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[1] = 0x80 | static_cast<unsigned char>(value & 0x3F);
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 2;
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((value <= 0xFFFF) && (buflen >= 3)) {
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[0] = 0xE0 | static_cast<unsigned char>(value >> 12);
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[1] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[2] = 0x80 | static_cast<unsigned char>(value & 0x3F);
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 3;
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((value <= 0x1FFFFF) && (buflen >= 4)) {
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[0] = 0xF0 | static_cast<unsigned char>(value >> 18);
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[1] = 0x80 | static_cast<unsigned char>((value >> 12) & 0x3F);
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[2] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[3] = 0x80 | static_cast<unsigned char>(value & 0x3F);
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 4;
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t html_encode(char * buffer, size_t buflen,
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                   const char * source, size_t srclen) {
2604dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = source[srcpos];
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ch < 128) {
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 1;
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (ASCII_CLASS[ch] & HTML_UNSAFE) {
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        const char * escseq = 0;
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        size_t esclen = 0;
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        switch (ch) {
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          case '<':  escseq = "&lt;";   esclen = 4; break;
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          case '>':  escseq = "&gt;";   esclen = 4; break;
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          case '\'': escseq = "&#39;";  esclen = 5; break;
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          case '\"': escseq = "&quot;"; esclen = 6; break;
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          case '&':  escseq = "&amp;";  esclen = 5; break;
2784dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org          default: DCHECK(false);
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (bufpos + esclen >= buflen) {
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          break;
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        memcpy(buffer + bufpos, escseq, esclen);
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        bufpos += esclen;
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        buffer[bufpos++] = ch;
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Largest value is 0x1FFFFF => &#2097151;  (10 characters)
2904dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org      const size_t kEscseqSize = 11;
2914dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org      char escseq[kEscseqSize];
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      unsigned long val;
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (size_t vallen = utf8_decode(&source[srcpos], srclen - srcpos, &val)) {
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        srcpos += vallen;
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Not a valid utf8 sequence, just use the raw character.
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        val = static_cast<unsigned char>(source[srcpos++]);
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
2994dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org      size_t esclen = sprintfn(escseq, kEscseqSize, "&#%lu;", val);
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (bufpos + esclen >= buflen) {
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      memcpy(buffer + bufpos, escseq, esclen);
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bufpos += esclen;
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t html_decode(char * buffer, size_t buflen,
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                   const char * source, size_t srclen) {
3134dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return xml_decode(buffer, buflen, source, srclen);
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t xml_encode(char * buffer, size_t buflen,
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char * source, size_t srclen) {
3194dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = source[srcpos++];
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ch < 128) && (ASCII_CLASS[ch] & XML_UNSAFE)) {
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      const char * escseq = 0;
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t esclen = 0;
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      switch (ch) {
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case '<':  escseq = "&lt;";   esclen = 4; break;
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case '>':  escseq = "&gt;";   esclen = 4; break;
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case '\'': escseq = "&apos;"; esclen = 6; break;
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case '\"': escseq = "&quot;"; esclen = 6; break;
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case '&':  escseq = "&amp;";  esclen = 5; break;
3354dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org        default: DCHECK(false);
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (bufpos + esclen >= buflen) {
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      memcpy(buffer + bufpos, escseq, esclen);
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bufpos += esclen;
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t xml_decode(char * buffer, size_t buflen,
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char * source, size_t srclen) {
3524dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen <= 0)
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = source[srcpos++];
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ch != '&') {
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = ch;
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos + 2 < srclen)
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (memcmp(source + srcpos, "lt;", 3) == 0)) {
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = '<';
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 3;
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos + 2 < srclen)
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (memcmp(source + srcpos, "gt;", 3) == 0)) {
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = '>';
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 3;
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos + 4 < srclen)
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (memcmp(source + srcpos, "apos;", 5) == 0)) {
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = '\'';
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 5;
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos + 4 < srclen)
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (memcmp(source + srcpos, "quot;", 5) == 0)) {
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = '\"';
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 5;
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos + 3 < srclen)
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               && (memcmp(source + srcpos, "amp;", 4) == 0)) {
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos++] = '&';
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      srcpos += 4;
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((srcpos < srclen) && (source[srcpos] == '#')) {
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int int_base = 10;
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if ((srcpos + 1 < srclen) && (source[srcpos+1] == 'x')) {
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        int_base = 16;
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        srcpos += 1;
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      char * ptr;
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // TODO: Fix hack (ptr may go past end of data)
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      unsigned long val = strtoul(source + srcpos + 1, &ptr, int_base);
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if ((static_cast<size_t>(ptr - source) < srclen) && (*ptr == ';')) {
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        srcpos = ptr - source + 1;
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Not a valid escape sequence.
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (size_t esclen = utf8_encode(buffer + bufpos, buflen - bufpos, val)) {
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        bufpos += esclen;
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Not enough room to encode the character, or illegal character
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Unrecognized escape sequence.
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const char HEX[] = "0123456789abcdef";
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgchar hex_encode(unsigned char val) {
4144dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK_LT(val, 16);
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (val < 16) ? HEX[val] : '!';
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool hex_decode(char ch, unsigned char* val) {
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((ch >= '0') && (ch <= '9')) {
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *val = ch - '0';
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if ((ch >= 'A') && (ch <= 'Z')) {
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *val = (ch - 'A') + 10;
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if ((ch >= 'a') && (ch <= 'z')) {
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *val = (ch - 'a') + 10;
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_encode(char* buffer, size_t buflen,
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char* csource, size_t srclen) {
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hex_encode_with_delimiter(buffer, buflen, csource, srclen, 0);
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_encode_with_delimiter(char* buffer, size_t buflen,
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const char* csource, size_t srclen,
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 char delimiter) {
4394dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(buffer);  // TODO: estimate output size
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen == 0)
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Init and check bounds.
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const unsigned char* bsource =
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      reinterpret_cast<const unsigned char*>(csource);
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t needed = delimiter ? (srclen * 3) : (srclen * 2 + 1);
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen < needed)
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (srcpos < srclen) {
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char ch = bsource[srcpos++];
45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[bufpos  ] = hex_encode((ch >> 4) & 0xF);
45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    buffer[bufpos+1] = hex_encode((ch     ) & 0xF);
45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    bufpos += 2;
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Don't write a delimiter after the last byte.
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (delimiter && (srcpos < srclen)) {
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      buffer[bufpos] = delimiter;
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ++bufpos;
46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Null terminate.
46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  buffer[bufpos] = '\0';
46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string hex_encode(const char* source, size_t srclen) {
47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hex_encode_with_delimiter(source, srclen, 0);
47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string hex_encode_with_delimiter(const char* source, size_t srclen,
47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      char delimiter) {
47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const size_t kBufferSize = srclen * 3;
47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char* buffer = STACK_ARRAY(char, kBufferSize);
47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = hex_encode_with_delimiter(buffer, kBufferSize,
47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                            source, srclen, delimiter);
4794dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(srclen == 0 || length > 0);
48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return std::string(buffer, length);
48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_decode(char * cbuffer, size_t buflen,
48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  const char * source, size_t srclen) {
48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hex_decode_with_delimiter(cbuffer, buflen, source, srclen, 0);
48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_decode_with_delimiter(char* cbuffer, size_t buflen,
48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const char* source, size_t srclen,
49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 char delimiter) {
4914dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(cbuffer);  // TODO: estimate output size
49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen == 0)
49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Init and bounds check.
49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer);
49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t srcpos = 0, bufpos = 0;
49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t needed = (delimiter) ? (srclen + 1) / 3 : srclen / 2;
49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (buflen < needed)
50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (srcpos < srclen) {
50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((srclen - srcpos) < 2) {
50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // This means we have an odd number of bytes.
50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned char h1, h2;
50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!hex_decode(source[srcpos], &h1) ||
51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        !hex_decode(source[srcpos + 1], &h2))
51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    bbuffer[bufpos++] = (h1 << 4) | h2;
51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    srcpos += 2;
51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Remove the delimiter if needed.
51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (delimiter && (srclen - srcpos) > 1) {
51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (source[srcpos] != delimiter)
51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return 0;
52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ++srcpos;
52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bufpos;
52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_decode(char* buffer, size_t buflen, const std::string& source) {
52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hex_decode_with_delimiter(buffer, buflen, source, 0);
52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t hex_decode_with_delimiter(char* buffer, size_t buflen,
53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const std::string& source, char delimiter) {
53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hex_decode_with_delimiter(buffer, buflen,
53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   source.c_str(), source.length(), delimiter);
53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t transform(std::string& value, size_t maxlen, const std::string& source,
53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                 Transform t) {
53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char* buffer = STACK_ARRAY(char, maxlen + 1);
53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = t(buffer, maxlen + 1, source.data(), source.length());
54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  value.assign(buffer, length);
54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return length;
54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string s_transform(const std::string& source, Transform t) {
54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Ask transformation function to approximate the destination size (returns upper bound)
54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t maxlen = t(NULL, 0, source.data(), source.length());
54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char * buffer = STACK_ARRAY(char, maxlen);
54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t len = t(buffer, maxlen, source.data(), source.length());
54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string result(buffer, len);
55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return result;
55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t tokenize(const std::string& source, char delimiter,
55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                std::vector<std::string>* fields) {
5554dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(fields);
55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fields->clear();
55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t last = 0;
55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t i = 0; i < source.length(); ++i) {
55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (source[i] == delimiter) {
56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (i != last) {
56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        fields->push_back(source.substr(last, i - last));
56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      last = i + 1;
56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (last != source.length()) {
56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    fields->push_back(source.substr(last, source.length() - last));
56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return fields->size();
57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t tokenize_append(const std::string& source, char delimiter,
57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                       std::vector<std::string>* fields) {
57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!fields) return 0;
57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::vector<std::string> new_fields;
57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  tokenize(source, delimiter, &new_fields);
57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fields->insert(fields->end(), new_fields.begin(), new_fields.end());
57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return fields->size();
58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t tokenize(const std::string& source, char delimiter, char start_mark,
58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                char end_mark, std::vector<std::string>* fields) {
58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!fields) return 0;
58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fields->clear();
58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string remain_source = source;
58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (!remain_source.empty()) {
58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t start_pos = remain_source.find(start_mark);
59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (std::string::npos == start_pos) break;
59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::string pre_mark;
59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (start_pos > 0) {
59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      pre_mark = remain_source.substr(0, start_pos - 1);
59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ++start_pos;
59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t end_pos = remain_source.find(end_mark, start_pos);
59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (std::string::npos == end_pos) break;
59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We have found the matching marks. First tokenize the pre-mask. Then add
60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // the marked part as a single field. Finally, loop back for the post-mark.
60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    tokenize_append(pre_mark, delimiter, fields);
60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    fields->push_back(remain_source.substr(start_pos, end_pos - start_pos));
60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    remain_source = remain_source.substr(end_pos + 1);
60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return tokenize_append(remain_source, delimiter, fields);
60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t split(const std::string& source, char delimiter,
61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org             std::vector<std::string>* fields) {
6124dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org  DCHECK(fields);
61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fields->clear();
61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t last = 0;
61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t i = 0; i < source.length(); ++i) {
61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (source[i] == delimiter) {
61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      fields->push_back(source.substr(last, i - last));
61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      last = i + 1;
61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fields->push_back(source.substr(last, source.length() - last));
62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return fields->size();
62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgchar make_char_safe_for_filename(char c) {
62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (c < 32)
62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return '_';
62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (c) {
63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '<':
63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '>':
63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case ':':
63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '"':
63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '/':
63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '\\':
63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '|':
63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '*':
63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case '?':
63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return '_';
64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    default:
64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return c;
64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid sprintf(std::string& value, size_t maxlen, const char * format, ...) {
64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char * buffer = STACK_ARRAY(char, maxlen + 1);
64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  va_list args;
65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  va_start(args, format);
65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  value.assign(buffer, vsprintfn(buffer, maxlen + 1, format, args));
65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  va_end(args);
65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org*/
65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
659