diff options
author | George Hazan <george.hazan@gmail.com> | 2012-06-23 17:15:01 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2012-06-23 17:15:01 +0000 |
commit | 240b769d44fe6c50cabbf311f8e9fb1fae7cd80e (patch) | |
tree | fb464ca81e54b3133a475b19fd4cdf811b789fad /src/modules/json/JSON_Base64.cpp | |
parent | 7a0f39abf558c7dde715a87d9356d92275d5d34e (diff) |
libjson interface added to the core
git-svn-id: http://svn.miranda-ng.org/main/trunk@573 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/json/JSON_Base64.cpp')
-rw-r--r-- | src/modules/json/JSON_Base64.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/modules/json/JSON_Base64.cpp b/src/modules/json/JSON_Base64.cpp new file mode 100644 index 0000000000..4759b112bb --- /dev/null +++ b/src/modules/json/JSON_Base64.cpp @@ -0,0 +1,136 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "..\..\core\commonheaders.h"
+
+#include "JSON_Base64.h" +#include "JSONDefs.h" + +#ifdef JSON_BINARY //if this is not needed, don't waste space compiling it + +static const json_char * chars64 = JSON_TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); +#ifdef JSON_UNICODE + static std::string BASE64_EMPTY_STRING; +#else + #define BASE64_EMPTY_STRING EMPTY_STRING +#endif + +json_string JSONBase64::json_encode64(const unsigned char * binary, size_t bytes){ + size_t misaligned = bytes % 3; + size_t aligned = (bytes - misaligned) / 3; //divide by three once and inc is faster than add 3 each time + json_string result; + result.reserve((size_t)(((float)bytes) * 1.37f) + 4); + + //do all of the ones that are 3 byte aligned + for (size_t i = 0; i < aligned; ++i){ + result += chars64[(binary[0] & 0xFC) >> 2]; + result += chars64[((binary[0] & 0x03) << 4) + ((binary[1] & 0xF0) >> 4)]; + result += chars64[((binary[1] & 0x0F) << 2) + ((binary[2] & 0xC0) >> 6)]; + result += chars64[binary[2] & 0x3F]; + binary += 3; + } + + if (misaligned){ + //copy the rest into a temporary buffer + unsigned char temp[3]; + for (unsigned int i = 0; i < misaligned; ++i){ + temp[i] = *binary++; + } + for (unsigned int i = (unsigned int)misaligned; i < 3; ++i){ + temp[i] = '\0'; + } + + //now do the final three bytes + result += chars64[(temp[0] & 0xFC) >> 2]; + result += chars64[((temp[0] & 0x03) << 4) + ((temp[1] & 0xF0) >> 4)]; + if (misaligned == 2){ + result += chars64[((temp[1] & 0x0F) << 2) + ((temp[2] & 0xC0) >> 6)]; + result += JSON_TEXT('='); + } else { + result += JSON_TEXT("=="); + } + } + JSON_ASSERT((size_t)(((float)bytes) * 1.37f) + 4 >= result.length(), JSON_TEXT("Didn't reserve enough space for a one-time go")); + return result; +} + +inline json_char toBinary(json_char c){ + if (c == JSON_TEXT('+')) { + return JSON_TEXT('>'); + } else if (c == JSON_TEXT('/')) { + return JSON_TEXT('?'); + } else if (c < JSON_TEXT(':')) { + return c + JSON_TEXT('\x04'); + } else if (c < JSON_TEXT('[')) { + return c - JSON_TEXT('\x41'); + } + return c - 71; +} + +/* + Must be a std::string because it's binary, and chars must be 1 byte + */ +std::string JSONBase64::json_decode64(const json_string & encoded){ + const size_t length = encoded.length(); + #if defined JSON_DEBUG || defined JSON_SAFE + size_t pos = encoded.find_first_not_of(chars64); + if (pos != json_string::npos){ + JSON_ASSERT_SAFE(encoded[pos] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;); + if (pos != length - 1){ + JSON_ASSERT_SAFE(pos == length - 2, JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;); + JSON_ASSERT_SAFE(encoded[pos + 1] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;); + } + } + #endif + const json_char * runner = encoded.c_str(); + size_t aligned = length / 4; //don't do the last ones as they might be = padding + std::string result; + if (aligned){ + --aligned; + result.reserve((size_t)((float)length / 1.37) + 1); + + //first do the ones that can not have any padding + for (unsigned int i = 0; i < aligned; ++i){ + const json_char second = toBinary(runner[1]); + const json_char third = toBinary(runner[2]); + result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4); + result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2); + result += ((third & 0x3) << 6) + toBinary(runner[3]); + runner += 4; + } + + //now do the ones that might have padding, the first two characters can not be padding, so do them quickly + const char second = toBinary(runner[1]); + result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4); + if (runner[2] != '=') { //not two = pads + const char third = toBinary(runner[2]); + result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2); + if (runner[3] != '=') { //no padding + result += ((third & 0x3) << 6) + toBinary(runner[3]); + } + } + } + return result; +} + +#endif |