File: pg_util.c

package info (click to toggle)
ruby-pg 1.5.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,264 kB
  • sloc: ansic: 8,820; ruby: 2,809; makefile: 10
file content (149 lines) | stat: -rw-r--r-- 4,705 bytes parent folder | download | duplicates (2)
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;
}