1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/*
* pg_util.c - Utils for ruby-pg
* $Id$
*
*/
#include "pg.h"
#include "pg_util.h"
static const char base64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* Encode _len_ bytes at _in_ as base64 and write output to _out_.
*
* This encoder runs backwards, so that it is possible to encode a string
* in-place (with _out_ == _in_).
*/
void
base64_encode( char *out, const char *in, int len)
{
const unsigned char *in_ptr = (const unsigned char *)in + len;
char *out_ptr = out + BASE64_ENCODED_SIZE(len);
int part_len = len % 3;
if( part_len > 0 ){
long byte2 = 0;
long byte1 = part_len > 1 ? *--in_ptr : 0;
long byte0 = *--in_ptr;
long triple = (byte0 << 16) + (byte1 << 8) + byte2;
*--out_ptr = '=';
*--out_ptr = part_len > 1 ? base64_encode_table[(triple >> 1 * 6) & 0x3F] : '=';
*--out_ptr = base64_encode_table[(triple >> 2 * 6) & 0x3F];
*--out_ptr = base64_encode_table[(triple >> 3 * 6) & 0x3F];
}
while( out_ptr > out ){
long byte2 = *--in_ptr;
long byte1 = *--in_ptr;
long byte0 = *--in_ptr;
long triple = (byte0 << 16) + (byte1 << 8) + byte2;
*--out_ptr = base64_encode_table[(triple >> 0 * 6) & 0x3F];
*--out_ptr = base64_encode_table[(triple >> 1 * 6) & 0x3F];
*--out_ptr = base64_encode_table[(triple >> 2 * 6) & 0x3F];
*--out_ptr = base64_encode_table[(triple >> 3 * 6) & 0x3F];
}
}
/*
* 0.upto(255).map{|a| "\\x#{ (base64_encode_table.index([a].pack("C")) || 0xff).to_s(16) }" }.join
*/
static const unsigned char base64_decode_table[] =
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3e\xff\xff\xff\x3f"
"\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xff\xff\xff\xff\xff\xff"
"\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
"\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\xff\xff\xff\xff\xff"
"\xff\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28"
"\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
/* Decode _len_ bytes of base64 characters at _in_ and write output to _out_.
*
* It is possible to decode a string in-place (with _out_ == _in_).
*/
int
base64_decode( char *out, const char *in, unsigned int len)
{
unsigned char a, b, c, d;
const unsigned char *in_ptr = (const unsigned char *)in;
unsigned char *out_ptr = (unsigned char *)out;
const unsigned char *iend_ptr = (unsigned char *)in + len;
for(;;){
if( in_ptr+3 < iend_ptr &&
(a=base64_decode_table[in_ptr[0]]) != 0xff &&
(b=base64_decode_table[in_ptr[1]]) != 0xff &&
(c=base64_decode_table[in_ptr[2]]) != 0xff &&
(d=base64_decode_table[in_ptr[3]]) != 0xff )
{
in_ptr += 4;
*out_ptr++ = (a << 2) | (b >> 4);
*out_ptr++ = (b << 4) | (c >> 2);
*out_ptr++ = (c << 6) | d;
} else if (in_ptr < iend_ptr){
b = c = d = 0xff;
while ((a = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
if (in_ptr < iend_ptr){
while ((b = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
if (in_ptr < iend_ptr){
while ((c = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
if (in_ptr < iend_ptr){
while ((d = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
}
}
}
if (a != 0xff && b != 0xff) {
*out_ptr++ = (a << 2) | (b >> 4);
if (c != 0xff) {
*out_ptr++ = (b << 4) | (c >> 2);
if (d != 0xff)
*out_ptr++ = (c << 6) | d;
}
}
} else {
break;
}
}
return (int)((char*)out_ptr - out);
}
/*
* Case-independent comparison of two not-necessarily-null-terminated strings.
* At most n bytes will be examined from each string.
*/
int
rbpg_strncasecmp(const char *s1, const char *s2, size_t n)
{
while (n-- > 0)
{
unsigned char ch1 = (unsigned char) *s1++;
unsigned char ch2 = (unsigned char) *s2++;
if (ch1 != ch2){
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
}
if (ch1 == 0)
break;
}
return 0;
}
|