1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//********************************************************************* 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* Base64 - a simple base64 encoder and decoder. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* Copyright (c) 1999, Bob Withers - bwit@pobox.com 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* This code may be freely used for any purpose, either personal 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* or commercial, provided the authors copyright notice remains 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* intact. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* Enhancements by Stanley Yamane: 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* o reverse lookup table for the decode function 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* o reserve string buffer space in advance 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//* 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//********************************************************************* 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/base64.h" 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochusing std::string; 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochusing std::vector; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const char kPad = '='; 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const unsigned char pd = 0xFD; // Padding 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const unsigned char sp = 0xFE; // Whitespace 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const unsigned char il = 0xFF; // Illegal base64 character 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst string Base64::Base64Table( 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// 0000000000111111111122222222223333333333444444444455555555556666 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// 0123456789012345678901234567890123456789012345678901234567890123 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Decode Table gives the index of any valid base64 character in the 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Base64 table 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// 65 == A, 97 == a, 48 == 0, 43 == +, 47 == / 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst unsigned char Base64::DecodeTable[] = { 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// 0 1 2 3 4 5 6 7 8 9 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,sp, // 0 - 9 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sp,sp,sp,sp,il,il,il,il,il,il, // 10 - 19 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 20 - 29 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,sp,il,il,il,il,il,il,il, // 30 - 39 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,62,il,il,il,63,52,53, // 40 - 49 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 54,55,56,57,58,59,60,61,il,il, // 50 - 59 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,pd,il,il,il, 0, 1, 2, 3, 4, // 60 - 69 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 5, 6, 7, 8, 9,10,11,12,13,14, // 70 - 79 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 15,16,17,18,19,20,21,22,23,24, // 80 - 89 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 25,il,il,il,il,il,il,26,27,28, // 90 - 99 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 29,30,31,32,33,34,35,36,37,38, // 100 - 109 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 39,40,41,42,43,44,45,46,47,48, // 110 - 119 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 49,50,51,il,il,il,il,il,il,il, // 120 - 129 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 130 - 139 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 140 - 149 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 150 - 159 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 160 - 169 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 170 - 179 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 180 - 189 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 190 - 199 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 200 - 209 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 210 - 219 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 220 - 229 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 230 - 239 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il,il,il,il,il, // 240 - 249 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch il,il,il,il,il,il // 250 - 255 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Base64::IsBase64Char(char ch) { 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (('A' <= ch) && (ch <= 'Z')) || 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (('a' <= ch) && (ch <= 'z')) || 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (('0' <= ch) && (ch <= '9')) || 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (ch == '+') || (ch == '/'); 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Base64::IsBase64Encoded(const std::string& str) { 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < str.size(); ++i) { 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsBase64Char(str.at(i))) 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Base64::EncodeFromArray(const void* data, size_t len, string* result) { 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(NULL != result); 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->clear(); 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->reserve(((len + 2) / 3) * 4); 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const unsigned char* byte_data = static_cast<const unsigned char*>(data); 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch unsigned char c; 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t i = 0; 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (i < len) { 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = (byte_data[i] >> 2) & 0x3f; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(Base64Table[c]); 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = (byte_data[i] << 4) & 0x3f; 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (++i < len) { 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c |= (byte_data[i] >> 4) & 0x0f; 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(Base64Table[c]); 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (i < len) { 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = (byte_data[i] << 2) & 0x3f; 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (++i < len) { 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c |= (byte_data[i] >> 6) & 0x03; 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(Base64Table[c]); 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(kPad); 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (i < len) { 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = byte_data[i] & 0x3f; 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(Base64Table[c]); 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++i; 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(kPad); 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochsize_t Base64::GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads, 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* data, size_t len, size_t* dpos, 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch unsigned char qbuf[4], bool* padded) 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch{ 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t byte_len = 0, pad_len = 0, pad_start = 0; 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (; (byte_len < 4) && (*dpos < len); ++*dpos) { 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch qbuf[byte_len] = DecodeTable[static_cast<unsigned char>(data[*dpos])]; 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((il == qbuf[byte_len]) || (illegal_pads && (pd == qbuf[byte_len]))) { 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parse_flags != DO_PARSE_ANY) 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore illegal characters 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (sp == qbuf[byte_len]) { 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parse_flags == DO_PARSE_STRICT) 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore spaces 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (pd == qbuf[byte_len]) { 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (byte_len < 2) { 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parse_flags != DO_PARSE_ANY) 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore unexpected padding 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (byte_len + pad_len >= 4) { 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parse_flags != DO_PARSE_ANY) 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore extra pads 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (1 == ++pad_len) { 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pad_start = *dpos; 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pad_len > 0) { 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parse_flags != DO_PARSE_ANY) 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore pads which are followed by data 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pad_len = 0; 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++byte_len; 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = byte_len; i < 4; ++i) { 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch qbuf[i] = 0; 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (4 == byte_len + pad_len) { 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *padded = true; 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *padded = false; 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pad_len) { 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Roll back illegal padding 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *dpos = pad_start; 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return byte_len; 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags, 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string* result, size_t* data_used) { 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return DecodeFromArrayTemplate<string>(data, len, flags, result, data_used); 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags, 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch vector<char>* result, size_t* data_used) { 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return DecodeFromArrayTemplate<vector<char> >(data, len, flags, result, 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch data_used); 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtemplate<typename T> 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Base64::DecodeFromArrayTemplate(const char* data, size_t len, 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DecodeFlags flags, T* result, 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t* data_used) 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch{ 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(NULL != result); 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(flags <= (DO_PARSE_MASK | DO_PAD_MASK | DO_TERM_MASK)); 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const DecodeFlags parse_flags = flags & DO_PARSE_MASK; 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const DecodeFlags pad_flags = flags & DO_PAD_MASK; 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const DecodeFlags term_flags = flags & DO_TERM_MASK; 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(0 != parse_flags); 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(0 != pad_flags); 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(0 != term_flags); 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->clear(); 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->reserve(len); 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t dpos = 0; 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool success = true, padded; 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch unsigned char c, qbuf[4]; 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (dpos < len) { 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t qlen = GetNextQuantum(parse_flags, (DO_PAD_NO == pad_flags), 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch data, len, &dpos, qbuf, &padded); 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = (qbuf[0] << 2) | ((qbuf[1] >> 4) & 0x3); 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (qlen >= 2) { 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(c); 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = ((qbuf[1] << 4) & 0xf0) | ((qbuf[2] >> 2) & 0xf); 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (qlen >= 3) { 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(c); 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = ((qbuf[2] << 6) & 0xc0) | qbuf[3]; 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (qlen >= 4) { 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->push_back(c); 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch c = 0; 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (qlen < 4) { 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((DO_TERM_ANY != term_flags) && (0 != c)) { 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch success = false; // unused bits 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((DO_PAD_YES == pad_flags) && !padded) { 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch success = false; // expected padding 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((DO_TERM_BUFFER == term_flags) && (dpos != len)) { 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch success = false; // unused chars 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (data_used) { 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *data_used = dpos; 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return success; 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 244