source: libcf/trunk/src/cf_codec.c@ 89

Last change on this file since 89 was 89, checked in by cheese, 11 years ago

#1 arrange dataset in codec

File size: 9.8 KB
Line 
1/**
2 * @file cf_codec.c
3 * @author myusgun <myusgun@gmail.com>
4 */
5#include "cf_codec.h"
6#include "cf_error.h"
7
8#include <string.h>
9#include <stdio.h>
10
11#define ASSERT_ARGS(x) \
12 if ((x)) \
13 return CF_ERROR_CODEC_INVALID_ARGS
14
15const static unsigned char g_ascii_HexDecode[] = {
16 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00 - 15 */
17 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16 - 31 */
18 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 - 47 */
19 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',0x00,0x00,0x00,0x00,0x00,0x00, /* 48 - 63 */
20 0x00, 'A', 'A', 'A', 'A', 'A', 'A',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 64 - 79 */
21 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80 - 95 */
22 0x00, 'a', 'a', 'a', 'a', 'a', 'a',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 - 111 */
23 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112 - 127 */
24 /* end of ascii character */
25 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128 - 143 */
26 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144 - 159 */
27 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 - 175 */
28 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 - 191 */
29 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192 - 207 */
30 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208 - 223 */
31 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224 - 239 */
32 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240 - 255 */
33};
34
35const static char g_table_Base64Encode[] = {
36#define PADDING_CHAR_INDEX 64
37 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 00 - 07 */
38 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 08 - 15 */
39 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 16 - 23 */
40 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 24 - 31 */
41 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 32 - 39 */
42 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 40 - 47 */
43 'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 48 - 55 */
44 '4', '5', '6', '7', '8', '9', '+', '/', /* 56 - 63 */
45 '=' /* padding */
46};
47
48const static unsigned char g_ascii_Base64Decode[] = {
49 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 00 - 15 */
50 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16 - 31 */
51 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 62,0xff,0xff,0xff, 63, /* 32 - 47 */
52 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,0xff,0xff,0xff, 64,0xff,0xff, /* 48 - 63 */
53 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64 - 79 */
54 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,0xff,0xff,0xff,0xff,0xff, /* 80 - 95 */
55 0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 96 - 111 */
56 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,0xff,0xff,0xff,0xff,0xff, /* 112 - 127 */
57 /* end of ascii character */
58 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 128 - 143 */
59 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144 - 159 */
60 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160 - 175 */
61 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 176 - 191 */
62 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 192 - 207 */
63 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 208 - 223 */
64 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 224 - 239 */
65 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 240 - 255 */
66};
67
68
69/**
70 * hex-encode
71 *
72 * @return 성공 시, CF_OK; 실패 시, 오류 코드
73 *
74 * @param bin 바이너리 데이터
75 * @param len 바이너리 데이터 길이
76 * @param hex 16진수 문자열을 저장할 주소
77 *
78 * @remark
79 * hex는 할당된 메모리이며, 크기는 '\0'를 포함하여 len * 2 + 1
80 */
81int
82CF_Codec_Hex_Encode (const unsigned char * bin,
83 const size_t len,
84 char * hex)
85{
86 size_t iter = 0;
87 size_t hexlen = len * 2 + 1;
88
89 const unsigned char * ptr = bin;
90
91 const static char hexchar[] = {'0', '1', '2', '3',
92 '4', '5', '6', '7',
93 '8', '9', 'a', 'b',
94 'c', 'd', 'e', 'f'};
95
96 ASSERT_ARGS (bin == NULL);
97 ASSERT_ARGS (hex == NULL);
98
99 for (iter = 0 ; iter < hexlen ; iter += 2, ptr++)
100 {
101 hex[iter ] = hexchar[((*(ptr)) >> 4) & 0x0f];
102 hex[iter + 1] = hexchar[((*(ptr)) ) & 0x0f];
103 }
104 hex[hexlen - 1] = '\0';
105
106 return CF_OK;
107}
108
109/**
110 * hex-decode
111 *
112 * @return 성공 시, CF_OK; 실패 시, 오류 코드
113 *
114 * @param hex 16진수 문자열
115 * @param bin 바이너리 데이터를 저장할 주소
116 * @param len 바이너리 데이터의 길이를 저장할 주소
117 *
118 * @remark
119 * bin는 할당된 메모리이며, 크기는 strlen (hex) / 2
120 */
121int
122CF_Codec_Hex_Decode (const char * hex,
123 unsigned char * bin,
124 size_t * len)
125{
126 int result = 0;
127
128 size_t length = strlen (hex); /* absolutely even-number */
129 size_t iter = 0;
130 size_t binlen = length / 2;
131
132 const char * ptr = hex;
133 char buf = 0;
134 unsigned char val = 0;
135 unsigned char asciiHex = 0;
136
137 ASSERT_ARGS (hex == NULL);
138 ASSERT_ARGS (bin == NULL);
139 ASSERT_ARGS (len == NULL);
140
141 for (iter = 0 ; iter < binlen ; iter++)
142 {
143 val = 0; /* init/re-init docoding-buffer */
144
145 /* decode one character */
146#define DECODE_HEX(x) \
147 do { \
148 buf = *(x); \
149 val = (unsigned char)(val << 4); \
150 asciiHex = g_ascii_HexDecode[(int)buf]; \
151 \
152 if (buf) \
153 val |= (unsigned char) \
154 (buf - asciiHex + (asciiHex == '0' ? 0 : 10)); \
155 else \
156 return CF_ERROR_CODEC_NOT_HEXSTRING; \
157 } while (0)
158
159 /* decode one byte by decode two character */
160 DECODE_HEX (ptr++);
161 DECODE_HEX (ptr++);
162
163 bin[iter] = val;
164 }
165
166 *len = binlen;
167
168 return result;
169}
170
171/**
172 * Base64-encode
173 *
174 * @return 성공 시, CF_OK; 실패 시, 오류 코드
175 *
176 * @param bin 바이너리 데이터
177 * @param len 바이너리 데이터 길이
178 * @param base64 base64 문자열을 저장할 주소
179 *
180 * @remark
181 * base64는 할당된 메모리이며, 크기는 '\0'를 포함하여 (((len + 2) / 3) * 4) + 1
182 *
183 * @see http://sourceforge.net/p/predef/wiki/Endianness/
184 */
185int
186CF_Codec_Base64_Encode (const unsigned char * bin,
187 const size_t len,
188 char * base64)
189{
190 size_t iter = 0;
191 char * ptr = base64;
192
193 ASSERT_ARGS (bin == NULL);
194 ASSERT_ARGS (base64 == NULL);
195
196#define SEXTUPLE_E_1(__x,_idx) ((__x[_idx ] >> 2) & 0x3f)
197#define SEXTUPLE_E_2(__x,_idx) ((__x[_idx ] << 4) & 0x30)
198#define SEXTUPLE_E_3(__x,_idx) ((__x[_idx + 1] >> 4) & 0x0f)
199#define SEXTUPLE_E_4(__x,_idx) ((__x[_idx + 1] << 2) & 0x3c)
200#define SEXTUPLE_E_5(__x,_idx) ((__x[_idx + 2] >> 6) & 0x03)
201#define SEXTUPLE_E_6(__x,_idx) ((__x[_idx + 2] ) & 0x3f)
202
203 for (iter = 0 ; iter < len - 2 ; iter += 3)
204 {
205 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_1 (bin, iter)];
206 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)|
207 SEXTUPLE_E_3 (bin, iter)];
208 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_4 (bin, iter)|
209 SEXTUPLE_E_5 (bin, iter)];
210 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_6 (bin, iter)];
211 }
212
213 if (iter < len)
214 {
215 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_1 (bin, iter)];
216
217 if (iter == (len - 1))
218 {
219 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)];
220 *ptr++ = g_table_Base64Encode[PADDING_CHAR_INDEX];
221 }
222 else
223 {
224 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)|
225 SEXTUPLE_E_3 (bin, iter)];
226 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_4 (bin, iter)];
227 }
228
229 *ptr++ = g_table_Base64Encode[PADDING_CHAR_INDEX];
230 }
231 *ptr = '\0';
232
233 return CF_OK;
234}
235
236/**
237 * Base64-decode
238 *
239 * @return 성공 시, CF_OK; 실패 시, 오류 코드
240 *
241 * @param base64 base64 문자열
242 * @param bin 바이너리 데이터를 저장할 주소
243 * @param len 바이너리 데이터의 길이를 저장할 주소
244 *
245 * @remark
246 * base64는 할당된 메모리이며, 크기는 (strlen (base64) - <'=' 개수>) / 4 * 3
247 *
248 * @see http://sourceforge.net/p/predef/wiki/Endianness/
249 */
250int
251CF_Codec_Base64_Decode (const char * base64,
252 unsigned char * bin,
253 size_t * len)
254{
255 size_t remain = 0;
256 const char * src = base64;
257 unsigned char * dst = bin;
258 size_t binlen = 0;
259
260 ASSERT_ARGS (base64 == NULL);
261 ASSERT_ARGS (bin == NULL);
262 ASSERT_ARGS (len == NULL);
263
264 while (*src && g_ascii_Base64Decode[(int)*src] < PADDING_CHAR_INDEX) src++;
265
266 if (*src)
267 return CF_ERROR_CODEC_NOT_BASE64;
268
269 remain = (size_t)(src - base64);
270 binlen = ((remain + 3) / 4) * 3;
271
272#define SEXTUPLE_D_1(src) (g_ascii_Base64Decode[(int)src[0]] << 2)
273#define SEXTUPLE_D_2(src) (g_ascii_Base64Decode[(int)src[1]] >> 4)
274#define SEXTUPLE_D_3(src) (g_ascii_Base64Decode[(int)src[1]] << 4)
275#define SEXTUPLE_D_4(src) (g_ascii_Base64Decode[(int)src[2]] >> 2)
276#define SEXTUPLE_D_5(src) (g_ascii_Base64Decode[(int)src[2]] << 6)
277#define SEXTUPLE_D_6(src) (g_ascii_Base64Decode[(int)src[3]] )
278
279 for (src = base64, dst = bin ; remain > 4 ; remain -= 4, src += 4)
280 {
281 *dst++ = (unsigned char)(SEXTUPLE_D_1 (src) | SEXTUPLE_D_2 (src));
282 *dst++ = (unsigned char)(SEXTUPLE_D_3 (src) | SEXTUPLE_D_4 (src));
283 *dst++ = (unsigned char)(SEXTUPLE_D_5 (src) | SEXTUPLE_D_6 (src));
284 }
285
286 if (remain > 1)
287 *dst++ = (unsigned char)(SEXTUPLE_D_1 (src) | SEXTUPLE_D_2 (src));
288
289 if (remain > 2)
290 *dst++ = (unsigned char)(SEXTUPLE_D_3 (src) | SEXTUPLE_D_4 (src));
291
292 if (remain > 3)
293 *dst++ = (unsigned char)(SEXTUPLE_D_5 (src) | SEXTUPLE_D_6 (src));
294
295 *dst++ = '\0';
296 *len = binlen;
297
298 return CF_OK;
299}
Note: See TracBrowser for help on using the repository browser.