RethinkDB native connector work, minor fixes.
This commit is contained in:
153
ext/librethinkdbxx/src/utils.cc
Normal file
153
ext/librethinkdbxx/src/utils.cc
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "utils.h"
|
||||
#include "error.h"
|
||||
|
||||
namespace RethinkDB {
|
||||
|
||||
size_t utf8_encode(unsigned int code, char* buf) {
|
||||
if (!(code & ~0x7F)) {
|
||||
buf[0] = code;
|
||||
return 1;
|
||||
} else if (!(code & ~0x7FF)) {
|
||||
buf[0] = 0xC0 | (code >> 6);
|
||||
buf[1] = 0x80 | (code & 0x3F);
|
||||
return 2;
|
||||
} else if (!(code & ~0xFFFF)) {
|
||||
buf[0] = 0xE0 | (code >> 12);
|
||||
buf[1] = 0x80 | ((code >> 6) & 0x3F);
|
||||
buf[2] = 0x80 | (code & 0x3F);
|
||||
return 3;
|
||||
} else if (!(code & ~0x1FFFFF)) {
|
||||
buf[0] = 0xF0 | (code >> 18);
|
||||
buf[1] = 0x80 | ((code >> 12) & 0x3F);
|
||||
buf[2] = 0x80 | ((code >> 6) & 0x3F);
|
||||
buf[3] = 0x80 | (code & 0x3F);
|
||||
return 4;
|
||||
} else if (!(code & ~0x3FFFFFF)) {
|
||||
buf[0] = 0xF8 | (code >> 24);
|
||||
buf[1] = 0x80 | ((code >> 18) & 0x3F);
|
||||
buf[2] = 0x80 | ((code >> 12) & 0x3F);
|
||||
buf[3] = 0x80 | ((code >> 6) & 0x3F);
|
||||
buf[4] = 0x80 | (code & 0x3F);
|
||||
return 5;
|
||||
} else if (!(code & ~0x7FFFFFFF)) {
|
||||
buf[0] = 0xFC | (code >> 30);
|
||||
buf[1] = 0x80 | ((code >> 24) & 0x3F);
|
||||
buf[2] = 0x80 | ((code >> 18) & 0x3F);
|
||||
buf[3] = 0x80 | ((code >> 12) & 0x3F);
|
||||
buf[4] = 0x80 | ((code >> 6) & 0x3F);
|
||||
buf[5] = 0x80 | (code & 0x3F);
|
||||
return 6;
|
||||
} else {
|
||||
throw Error("Invalid unicode codepoint %ud", code);
|
||||
}
|
||||
}
|
||||
|
||||
bool base64_decode(char c, int* out) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
*out = c - 'A';
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
*out = c - ('a' - 26);
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
*out = c - ('0' - 52);
|
||||
} else if (c == '+') {
|
||||
*out = 62;
|
||||
} else if (c == '/') {
|
||||
*out = 63;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool base64_decode(const std::string& in, std::string& out) {
|
||||
out.clear();
|
||||
out.reserve(in.size() * 3 / 4);
|
||||
auto read = in.begin();
|
||||
while (true) {
|
||||
int c[4];
|
||||
int end = 4;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (true) {
|
||||
if (read == in.end()) {
|
||||
c[i] = 0;
|
||||
end = i;
|
||||
i = 3;
|
||||
break;
|
||||
} else if (base64_decode(*read, &c[i])) {
|
||||
++read;
|
||||
break;
|
||||
} else {
|
||||
++read;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end == 1) return false;
|
||||
int val = c[0] << 18 | c[1] << 12 | c[2] << 6 | c[3];
|
||||
if (end > 1) out.append(1, val >> 16);
|
||||
if (end > 2) out.append(1, val >> 8 & 0xFF);
|
||||
if (end > 3) out.append(1, val & 0xFF);
|
||||
if (end != 4) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char base64_encode(unsigned int c) {
|
||||
if (c < 26) {
|
||||
return 'A' + c;
|
||||
} else if (c < 52) {
|
||||
return 'a' + c - 26;
|
||||
} else if (c < 62) {
|
||||
return '0' + c - 52;
|
||||
} else if (c == 62) {
|
||||
return '+';
|
||||
} else if (c == 63) {
|
||||
return '/';
|
||||
} else {
|
||||
throw Error("unreachable: base64 encoding %d", c);
|
||||
}
|
||||
}
|
||||
|
||||
void base64_encode(unsigned int* c, int n, std::string& out) {
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
out.append(1, base64_encode(c[0] >> 2));
|
||||
out.append(1, base64_encode((c[0] & 0x3) << 4 | c[1] >> 4));
|
||||
if (n == 1) {
|
||||
out.append("==");
|
||||
return;
|
||||
}
|
||||
out.append(1, base64_encode((c[1] & 0xF) << 2 | c[2] >> 6));
|
||||
if (n == 2) {
|
||||
out.append("=");
|
||||
return;
|
||||
}
|
||||
out.append(1, base64_encode(c[2] & 0x3F));
|
||||
}
|
||||
|
||||
std::string base64_encode(const std::string& in) {
|
||||
std::string out;
|
||||
out.reserve(in.size() * 4 / 3 + in.size() / 48 + 3);
|
||||
auto read = in.begin();
|
||||
while (true) {
|
||||
for (int group = 0; group < 16; ++group) {
|
||||
unsigned int c[3];
|
||||
int i = 0;
|
||||
for (; i < 3; ++i) {
|
||||
if (read == in.end()) {
|
||||
c[i] = 0;
|
||||
break;
|
||||
} else {
|
||||
c[i] = static_cast<unsigned char>(*read++);
|
||||
}
|
||||
}
|
||||
base64_encode(c, i, out);
|
||||
if (i != 3) {
|
||||
return out;
|
||||
}
|
||||
}
|
||||
out.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user