Changeset 88 in libcf
- Timestamp:
- 05/17/13 02:17:16 (11 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/cf_codec.h
r86 r88 7 7 * @example codec.c 8 8 */ 9 #ifndef __CF_CODEC_H__ 10 #define __CF_CODEC_H__ 11 9 12 #include "cf_base.h" 10 13 11 14 #include <stddef.h> 12 13 #ifndef __CF_CODEC_H__14 #define __CF_CODEC_H__15 15 16 16 #ifdef __cplusplus … … 19 19 20 20 CF_EXPORT int 21 CF_Codec_Hex_Encode (const unsigned char * bin,22 const size_t len,23 char * hex);21 CF_Codec_Hex_Encode (const unsigned char * bin, 22 const size_t len, 23 char * hex); 24 24 25 25 CF_EXPORT int 26 CF_Codec_Hex_Decode (const char * hex, 27 unsigned char * bin, 28 size_t * len); 26 CF_Codec_Hex_Decode (const char * hex, 27 unsigned char * bin, 28 size_t * len); 29 30 CF_EXPORT int 31 CF_Codec_Base64_Encode (const unsigned char * bin, 32 const size_t len, 33 char * base64); 34 35 CF_EXPORT int 36 CF_Codec_Base64_Decode (const char * base64, 37 unsigned char * bin, 38 size_t * len); 29 39 30 40 #ifdef __cplusplus -
trunk/include/cf_error.h
r80 r88 104 104 #define CF_ERROR_CODEC_INVALID_ARGS CF_ERROR_CODEC - 1 105 105 #define CF_ERROR_CODEC_NOT_HEXSTRING CF_ERROR_CODEC - 2 106 #define CF_ERROR_CODEC_NOT_BASE64 CF_ERROR_CODEC - 3 106 107 /* }}} codec */ 107 108 -
trunk/src/cf_codec.c
r86 r88 13 13 return CF_ERROR_CODEC_INVALID_ARGS 14 14 15 #define IS_NUMBER(x) (x >= '0' && x <= '9') 16 #define IS_LOWERCASE(x) (x >= 'a' && x <= 'f') 17 #define IS_UPPERCASE(x) (x >= 'A' && x <= 'F') 18 19 typedef unsigned char __uchar; 20 21 /** 22 * 바이너리 데이터를 16진수 문자열로 변환 15 const static unsigned char g_ascii_HexDecode[] = { 16 #define ASCN '0' /* ascii number */ 17 #define ASCU 'A' /* ascii upper */ 18 #define ASCL 'a' /* ascii lower */ 19 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00 - 15 */ 20 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16 - 31 */ 21 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 - 47 */ 22 ASCN,ASCN,ASCN,ASCN,ASCN,ASCN,ASCN,ASCN,ASCN,ASCN,0x00,0x00,0x00,0x00,0x00,0x00, /* 48 - 63 */ 23 0x00,ASCU,ASCU,ASCU,ASCU,ASCU,ASCU,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 64 - 79 */ 24 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80 - 95 */ 25 0x00,ASCL,ASCL,ASCL,ASCL,ASCL,ASCL,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 - 111 */ 26 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112 - 127 */ 27 /* end of ascii character */ 28 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128 - 143 */ 29 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144 - 159 */ 30 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 - 175 */ 31 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 - 191 */ 32 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192 - 207 */ 33 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208 - 223 */ 34 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224 - 239 */ 35 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240 - 255 */ 36 }; 37 38 const static char g_table_Base64Encode[] = { 39 #define PADDING_CHAR_INDEX 64 40 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 00 - 07 */ 41 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 08 - 15 */ 42 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 16 - 23 */ 43 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 24 - 31 */ 44 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 32 - 39 */ 45 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 40 - 47 */ 46 'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 48 - 55 */ 47 '4', '5', '6', '7', '8', '9', '+', '/', /* 56 - 63 */ 48 '=' /* padding */ 49 }; 50 51 const static unsigned char g_ascii_Base64Decode[] = { 52 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 00 - 15 */ 53 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 16 - 31 */ 54 99,99,99,99,99,99,99,99,99,99,99,62,99,99,99,63, /* 32 - 47 */ 55 52,53,54,55,56,57,58,59,60,61,99,99,99,64,99,99, /* 48 - 63 */ 56 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 64 - 79 */ 57 15,16,17,18,19,20,21,22,23,24,25,99,99,99,99,99, /* 80 - 95 */ 58 99,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 96 - 111 */ 59 41,42,43,44,45,46,47,48,49,50,51,99,99,99,99,99, /* 112 - 127 */ 60 /* end of ascii character */ 61 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 128 - 143 */ 62 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 144 - 159 */ 63 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 160 - 175 */ 64 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 176 - 191 */ 65 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 192 - 207 */ 66 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 208 - 223 */ 67 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 224 - 239 */ 68 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, /* 240 - 255 */ 69 }; 70 71 72 /** 73 * hex-encode 23 74 * 24 75 * @return 성공 시, CF_OK; 실패 시, 오류 코드 … … 29 80 * 30 81 * @remark 31 * 16진수 문자열을 저장할 메모리가 미리 할당되어야 하며, <br /> 32 * 크기는 null-character를 포함하여 len * 2 + 1 82 * hex는 할당된 메모리이며, 크기는 '\0'를 포함하여 len * 2 + 1 33 83 */ 34 84 int … … 37 87 char * hex) 38 88 { 39 size_t 40 size_t count= len * 2 + 1;41 42 const char hexchar[] = {'0', '1', '2', '3',43 '4', '5', '6', '7', 44 '8', '9', 'a', 'b',45 'c', 'd', 'e', 'f'};46 47 const __uchar * ptr = bin;89 size_t iter = 0; 90 size_t hexlen = len * 2 + 1; 91 92 const unsigned char * ptr = bin; 93 94 const static char hexchar[] = {'0', '1', '2', '3', 95 '4', '5', '6', '7', 96 '8', '9', 'a', 'b', 97 'c', 'd', 'e', 'f'}; 48 98 49 99 ASSERT_ARGS (bin == NULL); 50 100 ASSERT_ARGS (hex == NULL); 51 101 52 for (iter = 0 ; iter < count; iter += 2, ptr++)102 for (iter = 0 ; iter < hexlen ; iter += 2, ptr++) 53 103 { 54 104 hex[iter ] = hexchar[((*(ptr)) >> 4) & 0x0f]; 55 105 hex[iter + 1] = hexchar[((*(ptr)) ) & 0x0f]; 56 106 } 57 hex[ count- 1] = '\0';107 hex[hexlen - 1] = '\0'; 58 108 59 109 return CF_OK; … … 61 111 62 112 /** 63 * 16진수 문자열을 바이너리 데이터로 변환113 * hex-decode 64 114 * 65 115 * @return 성공 시, CF_OK; 실패 시, 오류 코드 … … 70 120 * 71 121 * @remark 72 * 바이너리 데이터를 저장할 메모리가 미리 할당되어야 하며, <br /> 73 * 크기는 strlen (hex) / 2 122 * bin는 할당된 메모리이며, 크기는 strlen (hex) / 2 74 123 */ 75 124 int … … 80 129 int result = 0; 81 130 82 size_t length = strlen (hex); 131 size_t length = strlen (hex); /* absolutely even-number */ 83 132 size_t iter = 0; 84 size_t count= length / 2;85 int twochar = 0; 86 87 c onst char * ptr = hex;88 char buf= 0;89 __uchar val= 0;133 size_t binlen = length / 2; 134 135 const char * ptr = hex; 136 char buf = 0; 137 unsigned char val = 0; 138 unsigned char asciiHex = 0; 90 139 91 140 ASSERT_ARGS (hex == NULL); … … 93 142 ASSERT_ARGS (len == NULL); 94 143 95 for (iter = 0 ; iter < count ; iter++) 96 { 97 for (twochar = 2, val = 0 ; twochar ; ptr++, twochar--) 98 { 99 buf = *ptr; 100 val = (__uchar)(val << 4); 101 102 if (IS_NUMBER (buf)) val |= (__uchar)(buf - '0' + 0); 103 else if (IS_LOWERCASE (buf)) val |= (__uchar)(buf - 'a' + 10); 104 else if (IS_UPPERCASE (buf)) val |= (__uchar)(buf - 'A' + 10); 105 else 106 { 107 result = CF_ERROR_CODEC_NOT_HEXSTRING; 108 break; 109 } 110 } 144 for (iter = 0 ; iter < binlen ; iter++) 145 { 146 val = 0; /* init/re-init docoding-buffer */ 147 148 /* decode one character */ 149 #define DECODE_HEX(x) \ 150 do { \ 151 buf = *(x); \ 152 val = (unsigned char)(val << 4); \ 153 asciiHex = g_ascii_HexDecode[(int)buf]; \ 154 \ 155 if (buf) \ 156 val |= (unsigned char) \ 157 (buf - asciiHex + (asciiHex == ASCN ? 0 : 10)); \ 158 else \ 159 return CF_ERROR_CODEC_NOT_HEXSTRING; \ 160 } while (0) 161 162 /* decode one byte by decode two character */ 163 DECODE_HEX (ptr++); 164 DECODE_HEX (ptr++); 111 165 112 166 bin[iter] = val; 113 167 } 114 168 115 if (result == 0) 116 *len = count; 169 *len = binlen; 117 170 118 171 return result; 119 172 } 173 174 /** 175 * Base64-encode 176 * 177 * @return 성공 시, CF_OK; 실패 시, 오류 코드 178 * 179 * @param bin 바이너리 데이터 180 * @param len 바이너리 데이터 길이 181 * @param base64 base64 문자열을 저장할 주소 182 * 183 * @remark 184 * base64는 할당된 메모리이며, 크기는 '\0'를 포함하여 (((len + 2) / 3) * 4) + 1 185 * 186 * @see http://sourceforge.net/p/predef/wiki/Endianness/ 187 */ 188 int 189 CF_Codec_Base64_Encode (const unsigned char * bin, 190 const size_t len, 191 char * base64) 192 { 193 size_t iter = 0; 194 char * ptr = base64; 195 196 ASSERT_ARGS (bin == NULL); 197 ASSERT_ARGS (base64 == NULL); 198 199 #define SEXTUPLE_E_1(__x,_idx) ((__x[_idx ] >> 2) & 0x3f) 200 #define SEXTUPLE_E_2(__x,_idx) ((__x[_idx ] << 4) & 0x30) 201 #define SEXTUPLE_E_3(__x,_idx) ((__x[_idx + 1] >> 4) & 0x0f) 202 #define SEXTUPLE_E_4(__x,_idx) ((__x[_idx + 1] << 2) & 0x3c) 203 #define SEXTUPLE_E_5(__x,_idx) ((__x[_idx + 2] >> 6) & 0x03) 204 #define SEXTUPLE_E_6(__x,_idx) ((__x[_idx + 2] ) & 0x3f) 205 206 for (iter = 0 ; iter < len - 2 ; iter += 3) 207 { 208 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_1 (bin, iter)]; 209 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)| 210 SEXTUPLE_E_3 (bin, iter)]; 211 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_4 (bin, iter)| 212 SEXTUPLE_E_5 (bin, iter)]; 213 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_6 (bin, iter)]; 214 } 215 216 if (iter < len) 217 { 218 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_1 (bin, iter)]; 219 220 if (iter == (len - 1)) 221 { 222 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)]; 223 *ptr++ = g_table_Base64Encode[PADDING_CHAR_INDEX]; 224 } 225 else 226 { 227 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_2 (bin, iter)| 228 SEXTUPLE_E_3 (bin, iter)]; 229 *ptr++ = g_table_Base64Encode[SEXTUPLE_E_4 (bin, iter)]; 230 } 231 232 *ptr++ = g_table_Base64Encode[PADDING_CHAR_INDEX]; 233 } 234 *ptr = '\0'; 235 236 return CF_OK; 237 } 238 239 /** 240 * Base64-decode 241 * 242 * @return 성공 시, CF_OK; 실패 시, 오류 코드 243 * 244 * @param base64 base64 문자열 245 * @param bin 바이너리 데이터를 저장할 주소 246 * @param len 바이너리 데이터의 길이를 저장할 주소 247 * 248 * @remark 249 * base64는 할당된 메모리이며, 크기는 (strlen (base64) - <'=' 개수>) / 4 * 3 250 * 251 * @see http://sourceforge.net/p/predef/wiki/Endianness/ 252 */ 253 int 254 CF_Codec_Base64_Decode (const char * base64, 255 unsigned char * bin, 256 size_t * len) 257 { 258 size_t remain = 0; 259 const char * src = base64; 260 unsigned char * dst = bin; 261 size_t binlen = 0; 262 263 ASSERT_ARGS (base64 == NULL); 264 ASSERT_ARGS (bin == NULL); 265 ASSERT_ARGS (len == NULL); 266 267 while (*src && g_ascii_Base64Decode[(int)*src] < PADDING_CHAR_INDEX) src++; 268 269 if (*src) 270 return CF_ERROR_CODEC_NOT_BASE64; 271 272 remain = (size_t)(src - base64); 273 binlen = ((remain + 3) / 4) * 3; 274 275 #define SEXTUPLE_D_1(src) (g_ascii_Base64Decode[(int)src[0]] << 2) 276 #define SEXTUPLE_D_2(src) (g_ascii_Base64Decode[(int)src[1]] >> 4) 277 #define SEXTUPLE_D_3(src) (g_ascii_Base64Decode[(int)src[1]] << 4) 278 #define SEXTUPLE_D_4(src) (g_ascii_Base64Decode[(int)src[2]] >> 2) 279 #define SEXTUPLE_D_5(src) (g_ascii_Base64Decode[(int)src[2]] << 6) 280 #define SEXTUPLE_D_6(src) (g_ascii_Base64Decode[(int)src[3]] ) 281 282 for (src = base64, dst = bin ; remain > 4 ; remain -= 4, src += 4) 283 { 284 *dst++ = (unsigned char)(SEXTUPLE_D_1 (src) | SEXTUPLE_D_2 (src)); 285 *dst++ = (unsigned char)(SEXTUPLE_D_3 (src) | SEXTUPLE_D_4 (src)); 286 *dst++ = (unsigned char)(SEXTUPLE_D_5 (src) | SEXTUPLE_D_6 (src)); 287 } 288 289 if (remain > 1) 290 *dst++ = (unsigned char)(SEXTUPLE_D_1 (src) | SEXTUPLE_D_2 (src)); 291 292 if (remain > 2) 293 *dst++ = (unsigned char)(SEXTUPLE_D_3 (src) | SEXTUPLE_D_4 (src)); 294 295 if (remain > 3) 296 *dst++ = (unsigned char)(SEXTUPLE_D_5 (src) | SEXTUPLE_D_6 (src)); 297 298 *dst++ = '\0'; 299 *len = binlen; 300 301 return CF_OK; 302 } -
trunk/test/codec.c
r86 r88 12 12 char data[] = "ONE OK ROCK - Nothing Helps"; 13 13 14 char hex[512] = {0x00,};14 char encode[512] = {0x00,}; 15 15 unsigned char bin[512] = {0x00,}; 16 16 size_t length = 0; 17 17 18 /* hex */ 19 CF_DEBUG_PRINT (stderr, "------------------- codec/hex ----------------\n"); 18 20 CF_DEBUG_PRINT (stderr, "data : %s\n", data); 19 21 CF_DEBUG_PRINT (stderr, "= Convert binary to hex =\n"); 20 CF_Codec_Hex_Encode ((unsigned char *)data, strlen (data), hex);21 CF_DEBUG_PRINT (stderr, "hex : %s\n", hex);22 CF_Codec_Hex_Encode ((unsigned char *)data, strlen (data), encode); 23 CF_DEBUG_PRINT (stderr, "hex : %s\n", encode); 22 24 CF_DEBUG_PRINT_BIN (stderr, (unsigned char *) data, strlen (data), "data : %s\n", data); 23 25 24 26 CF_DEBUG_PRINT (stderr, "= Convert hex to binary =\n"); 25 CF_Codec_Hex_Decode (hex, bin, &length); 27 CF_Codec_Hex_Decode (encode, bin, &length); 28 CF_DEBUG_PRINT_BIN (stderr, bin, length, "bin : %s\n", bin); 29 30 memset (bin , 0x00, sizeof (bin)); 31 memset (encode, 0x00, sizeof (encode)); 32 length = 0; 33 34 /* base64 */ 35 CF_DEBUG_PRINT (stderr, "----------------- codec/base64 ---------------\n"); 36 CF_DEBUG_PRINT (stderr, "data : %s\n", data); 37 CF_DEBUG_PRINT (stderr, "= Convert binary to base64 =\n"); 38 CF_Codec_Base64_Encode ((unsigned char *)data, strlen (data), encode); 39 CF_DEBUG_PRINT (stderr, "base64 : %s\n", encode); 40 41 CF_DEBUG_PRINT (stderr, "= Convert base64 to binary =\n"); 42 CF_Codec_Base64_Decode (encode, bin, &length); 26 43 CF_DEBUG_PRINT_BIN (stderr, bin, length, "bin : %s\n", bin); 27 44 -
trunk/test/test.c
r86 r88 387 387 char data[] = "ONE OK ROCK - Nothing Helps"; 388 388 389 char hex[512] = {0x00,};389 char encode[512] = {0x00,}; 390 390 unsigned char bin[512] = {0x00,}; 391 391 size_t length = 0; 392 392 393 /* hex */ 394 CF_DEBUG_PRINT (stderr, "------------------- codec/hex ----------------\n"); 393 395 CF_DEBUG_PRINT (stderr, "data : %s\n", data); 394 396 CF_DEBUG_PRINT (stderr, "= Convert binary to hex =\n"); 395 CF_Codec_Hex_Encode ((unsigned char *)data, strlen (data), hex);396 CF_DEBUG_PRINT (stderr, "hex : %s\n", hex);397 CF_Codec_Hex_Encode ((unsigned char *)data, strlen (data), encode); 398 CF_DEBUG_PRINT (stderr, "hex : %s\n", encode); 397 399 CF_DEBUG_PRINT_BIN (stderr, (unsigned char *) data, strlen (data), "data : %s\n", data); 398 400 399 401 CF_DEBUG_PRINT (stderr, "= Convert hex to binary =\n"); 400 CF_Codec_Hex_Decode ( hex, bin, &length);402 CF_Codec_Hex_Decode (encode, bin, &length); 401 403 CF_DEBUG_PRINT_BIN (stderr, bin, length, "bin : %s\n", bin); 402 } 404 405 memset (bin , 0x00, sizeof (bin)); 406 memset (encode, 0x00, sizeof (encode)); 407 length = 0; 408 409 /* base64 */ 410 CF_DEBUG_PRINT (stderr, "----------------- codec/base64 ---------------\n"); 411 CF_DEBUG_PRINT (stderr, "data : %s\n", data); 412 CF_DEBUG_PRINT (stderr, "= Convert binary to base64 =\n"); 413 CF_Codec_Base64_Encode ((unsigned char *)data, strlen (data), encode); 414 CF_DEBUG_PRINT (stderr, "base64 : %s\n", encode); 415 416 CF_DEBUG_PRINT (stderr, "= Convert base64 to binary =\n"); 417 CF_Codec_Base64_Decode (encode, bin, &length); 418 CF_DEBUG_PRINT_BIN (stderr, bin, length, "bin : %s\n", bin); 419 }
Note:
See TracChangeset
for help on using the changeset viewer.