/* * 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; }