File: //usr/local/rvm/gems/default/gems/pg-1.2.3/ext/pg_util.c
/*
* 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){
a = 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 (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;
}