/* Copyright (c) 2000-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkenc.c Encoding module. */ #include "dk.h" #include "dktypes.h" #include "dkmem.h" #include "dkerror.h" #include "dkma.h" #if DK_HAVE_CTYPE_H #include #endif /** Inside the dkenc module. */ #define DK_ENC_C 1 #include "dkenc.h" #line 64 "dkenc.ctr" /** Abbreviation for use in prototypes. */ typedef unsigned long UL; /** Abbreviation for use in prototypes. */ typedef unsigned short US; /** Abbreviation for use in prototypes. */ typedef unsigned char UC; /** Factors to add ASCII85-digits to byte quadrupel. */ static unsigned long f2[] = { 1UL, 85UL, (85UL * 85UL), (85UL * 85UL * 85UL), (85UL * 85UL * 85UL * 85UL) }; static unsigned long last_byte = 0x000000FFUL; #if !DK_WORDS_BIGENDIAN /** Swap unsigned long (change byte order). @param x Value to convert. @return Conversion result. */ static unsigned long swapul DK_P1(unsigned long, x) { unsigned long back; unsigned char *uc1, *uc2; size_t i; uc1 = (unsigned char *)(&x); uc2 = (unsigned char *)(&back); for(i = 0; i < sizeof(UL); i++) { uc2[i] = uc1[(sizeof(UL) - 1 - i)]; } return back; } /** Swap unsigned short (change byte order). @param x Value to convert. @return Conversion result. */ static unsigned short swapus DK_P1(unsigned short, x) { unsigned short back; unsigned char *uc1, *uc2; size_t i; uc1 = (unsigned char *)(&x); uc2 = (unsigned char *)(&back); for(i = 0; i < sizeof(US); i++) { uc2[i] = uc1[(sizeof(US) - 1 - i)]; } return back; } #endif /* if !DK_WORDS_BIGENDIAN */ unsigned long dkenc_ntohl DK_P1(unsigned long, x) { unsigned long back; #if DK_WORDS_BIGENDIAN back = x; #else back = swapul(x); #endif return back; } unsigned long dkenc_htonl DK_P1(unsigned long, x) { unsigned long back; #if DK_WORDS_BIGENDIAN back = x; #else back = swapul(x); #endif return back; } unsigned short dkenc_ntohs DK_P1(unsigned short, x) { unsigned short back; #if DK_WORDS_BIGENDIAN back = x; #else back = swapus(x); #endif return back; } unsigned short dkenc_htons DK_P1(unsigned short, x) { unsigned short back; #if DK_WORDS_BIGENDIAN back = x; #else back = swapus(x); #endif return back; } /** Convert 32-bit character to UTF-8. @param c The 32-bit character. @param u8p Buffer to receive UTF-8 encoded result. @param u8l Length of \a u8l. @return The number of bytes produced. */ size_t dkenc_uc2utf8 DK_P3(dk_udword, c, dk_ubyte *, u8p, size_t, u8l) { size_t back = 0; dk_udword x; if(u8p) { if(u8l > 0) { if(c > 0x7FUL) { if(c > 0x000007FFUL) { if(c > 0x0000FFFFUL) { if(c > 0x001FFFFFUL) { if(c > 0x03FFFFFFUL) { if(c < 0x80000000UL) { /* 6 Byte */ if(u8l >= 6) { back = 6; x = c >> 30; x &= 0x00000001UL; x |= 0x000000FCUL; u8p[0] = (dk_ubyte)x; x = c >> 24; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[1] = (dk_ubyte)x; x = c >> 18; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[2] = (dk_ubyte)x; x = c >> 12; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[3] = (dk_ubyte)x; x = c >> 6; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[4] = (dk_ubyte)x; x = c & 0x0000003FUL; x |= 0x00000080UL; u8p[5] = (dk_ubyte)x; } } } else { /* 5 Byte */ if(u8l >= 5) { back = 5; x = c >> 24; x &= 0x00000003UL; x |= 0x000000F8UL; u8p[0] = (dk_ubyte)x; x = c >> 18; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[1] = (dk_ubyte)x; x = c >> 12; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[2] = (dk_ubyte)x; x = c >> 6; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[3] = (dk_ubyte)x; x = c & 0x0000003FUL; x |= 0x00000080UL; u8p[4] = (dk_ubyte)x; } } } else { /* 4 Byte */ if(u8l >= 4) { back = 4; x = c >> 18; x &= 0x00000007UL; x |= 0x000000F0UL; u8p[0] = (dk_ubyte)x; x = c >> 12; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[1] = (dk_ubyte)x; x = c >> 6; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[2] = (dk_ubyte)x; x = c & 0x0000003FUL; x |= 0x00000080UL; u8p[3] = (dk_ubyte)x; } } } else { /* 3 Byte */ if(u8l >= 3) { back = 3; x = c >> 12; x &= 0x0000000FUL; x |= 0x000000E0UL; u8p[0] = (dk_ubyte)x; x = c >> 6; x &= 0x0000003FUL; x |= 0x00000080UL; u8p[1] = (dk_ubyte)x; x = c & 0x0000003FUL; x |= 0x00000080UL; u8p[2] = (dk_ubyte)x; } } } else { /* 2 Byte */ if(u8l >= 2) { back = 2; x = c >> 6; x &= 0x0000001FUL; x |= 0x000000C0UL; u8p[0] = (dk_ubyte)x; x = c & 0x0000003FUL; x |= 0x00000080UL; u8p[1] = (dk_ubyte)x; } } } else { /* 1 Byte */ if(u8l >= 1) { back = 1; u8p[0] = (dk_ubyte)(c & 0x0000007FUL); } } } } return back; } /** Convert UTF-8 encoded text to 32-bit character. @param ucp Pointer to variable for result. @param u8p Buffer containing UTF-8 encoded text. @param u8l Number of bytes in buffer. @param u8u Pointer to variable to receive number of bytes used. @return 1 on success, 0 on error. */ int dkenc_utf82uc DK_P4(dk_udword *, ucp, dk_ubyte *, u8p, size_t , u8l, size_t *, u8u) { int back = 0; dk_ubyte u1; dk_udword res, x1, x2, x3, x4, x5, x6; size_t needed_length; needed_length = 0; if(ucp) { if(u8p) { if(u8l) { if(u8u) { if((u8l) > 0) { u1 = *u8p; needed_length = 1; if(u1 > 0x7F) { /* > 1 Byte */ if((u1 & 0xE0) == 0xC0) { /* 2 Byte */ needed_length = 2; if(u8l >= needed_length) { if((u8p[1] & 0xC0) == 0x80) { x1 = u1; x1 = x1 << 6; x1 = x1 & 0x000007C0UL; x2 = u8p[1]; x2 = x2 & 0x0000003FUL; res = (x1 | x2); back = 1; } } } else { if((u1 & 0xF0) == 0xE0) { /* 3 Byte */ needed_length = 3; if(u8l >= needed_length) { if((u8p[1] & 0xC0) == 0x80) { if((u8p[2] & 0xC0) == 0x80) { x1 = u1; x1 = x1 << 12; x1 = x1 & 0x0000F000UL; x2 = u8p[1]; x2 = x2 << 6; x2 = x2 & 0x00000FC0UL; x3 = u8p[2]; x3 = x3 & 0x0000003FUL; res = (x1 | x2 | x3); back = 1; } } } } else { if((u1 & 0xF8) == 0xF0) { /* 4 Byte */ needed_length = 4; if(u8l >= needed_length) { if((u8p[1] & 0xC0) == 0x80) { if((u8p[2] & 0xC0) == 0x80) { if((u8p[3] & 0xC0) == 0x80) { x1 = u1; x2 = u8p[1]; x3 = u8p[2]; x4 = u8p[3]; x1 = x1 << 18; x1 = x1 & 0x001C0000UL; x2 = x2 << 12; x2 = x2 & 0x0003F000UL; x3 = x3 << 6; x3 = x3 & 0x00000FC0UL; x4 = x4 & 0x0000003FUL; res = (x1 | x2 | x3 | x4); back = 1; } } } } } else { if((u1 & 0xFC) == 0xF8) { /* 5 Byte */ needed_length = 5; if(u8l >= needed_length) { if((u8p[1] & 0xC0) == 0x80) { if((u8p[2] & 0xC0) == 0x80) { if((u8p[3] & 0xC0) == 0x80) { if((u8p[4] & 0xC0) == 0x80) { x1 = u1; x2 = u8p[1]; x3 = u8p[2]; x4 = u8p[3]; x5 = u8p[4]; x1 = x1 << 24; x1 = x1 & 0x03000000UL; x2 = x2 << 18; x2 = x2 & 0x00FC0000UL; x3 = x3 << 12; x3 = x3 & 0x0003F000UL; x4 = x4 << 6; x4 = x4 & 0x00000FC0UL; x5 = x5 & 0x0000003FUL; res = (x1 | x2 | x3 | x4 | x5); back = 1; } } } } } } else { if((u1 & 0xFE) == 0xFC) { /* 6 Byte */ needed_length = 6; if(u8l >= needed_length) { if((u8p[1] & 0xC0) == 0x80) { if((u8p[2] & 0xC0) == 0x80) { if((u8p[3] & 0xC0) == 0x80) { if((u8p[4] & 0xC0) == 0x80) { if((u8p[5] & 0xC0) == 0x80) { x1 = 0x40000000UL; x2 = u8p[1]; x3 = u8p[2]; x4 = u8p[3]; x5 = u8p[4]; x6 = u8p[5]; x2 = x2 << 24; x3 = x3 << 18; x4 = x4 << 12; x5 = x5 << 6; x2 = x2 & 0x3F000000UL; x3 = x3 & 0x00FC0000UL; x4 = x4 & 0x0003F000UL; x5 = x5 & 0x00000FC0UL; x6 = x6 & 0x0000003FUL; res = (x1 | x2 | x3 | x4 | x5 | x6); back = 1; } } } } } } } } } } } } else { /* 1 Byte */ res = u1; back = 1; } } } } } } if(back) { *u8u = needed_length; *ucp = res; } return back; } #if !DK_HAVE_ISDIGIT /** Check whether a character is a digit. @param c Character to check. @return 1 on success, 0 on error. */ static int my_is_digit DK_P1(char,c) { int back = 0; switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { back = 1; } break; } return back; } #endif /** Convert digit to corresponding unsigned long. @param c Digit. @return Unsigned long for the digit. */ static unsigned long char_to_ul DK_P1(char, c) { unsigned long back = 0UL; if(c == '1') back = 1UL; if(c == '2') back = 2UL; if(c == '3') back = 3UL; if(c == '4') back = 4UL; if(c == '5') back = 5UL; if(c == '6') back = 6UL; if(c == '7') back = 7UL; if(c == '8') back = 8UL; if(c == '9') back = 9UL; return back; } int dkenc_ipaddr_to_ul DK_P2(char *,str,unsigned long *,ul) { int back = 0; int state; char *ptr; unsigned long ul1, ul2, ul3, ulval; if(str && ul) { state = 0; ptr = str; back = 1; ul1 = ul2 = ul3 = ulval = 0UL; while(back && (*ptr)) { if(isdigit(*ptr)) { switch(state) { case 0: case 1: case 2: case 4: case 5: case 6: case 8: case 9: case 10: case 12: case 13: case 14: { ulval = 10UL * ulval + char_to_ul(*ptr); state++; } break; default: { back = 0; } break; } } else { if(*ptr == '.') { switch(state) { case 0: case 1: case 2: case 3: { ul1 = ulval; ulval = 0UL; state = 4; } break; case 4: case 5: case 6: case 7: { ul2 = ulval; ulval = 0UL; state = 8; } break; case 8: case 9: case 10: case 11: { ul3 = ulval; ulval = 0UL; state = 12; } break; } } else { back = 0; } } ptr++; } if((state < 12) || (state > 15)) { back = 0; } if(back) { if(ul1 > 255UL) back = 1; if(ul2 > 255UL) back = 1; if(ul3 > 255UL) back = 1; if(ulval > 255UL) back = 1; } if(back) { ul1 = ul1 << 24; ul1 &= 0xFF000000UL; ul2 = ul2 << 16; ul2 &= 0x00FF0000UL; ul3 = ul3 << 8; ul3 &= 0x0000FF00UL; ulval &= 0x000000FFUL; ulval = ulval | ul1 | ul2 | ul3; *ul = ulval; } } return back; } /* Convert UTF-8 encoded string to 8-bit LATIN-1. The result is a new string, you must release it using dk_delete(). */ char *dkenc_str_utf82bits8 DK_P2(char *,s, int *,ecp) { char *back = NULL; /* function result */ int me; /* my error code */ int cc; /* can continue */ size_t lgt; /* string length after recoding */ size_t sl; /* original string length */ size_t ni; /* start index of byte for current conversion */ size_t used; /* bytes used in current conversion */ size_t newlength; /* temporary value, summary of used bytes */ dk_udword uw; dk_ubyte ub; char c; if(s) { me = 0; lgt = 1; sl = strlen(s); cc = 1; ni = 0; while((cc) && (ni < sl)) { used = 0; if(dkenc_utf82uc(&uw, (dk_ubyte *)(&(s[ni])),(sl-ni),&used)) { lgt++; newlength = ni + used; if(newlength > ni) { ni = newlength; if(newlength >= sl) { cc = 0; } } else { me = 1; cc = 0; if(ecp) { *ecp = DK_ERR_INVALID_ARGS; } } } else { cc = 0; me = 1; if(ecp) { *ecp = DK_ERR_INVALID_ARGS; } } } if((!me)) { back = dk_new(char,lgt); if(back) { ni = 0; cc = 1; lgt = 0; while((cc) && (ni < sl)) { used = 0; if(dkenc_utf82uc(&uw, (dk_ubyte *)(&(s[ni])),(sl-ni),&used)) { if(uw <= 0x000000FFUL) { ub = (dk_ubyte)uw; c = (char)ub; } else { c = '.'; if(ecp) { *ecp = DK_ERR_MATH_OOR; } } back[lgt++] = c; newlength = ni + used; if(newlength > ni) { ni = newlength; if(newlength >= sl) { cc = 0; } } else { me = 1; cc = 0; if(ecp) { *ecp = DK_ERR_INVALID_ARGS; } } } else { me = 1; cc = 0; if(ecp) { *ecp = DK_ERR_INVALID_ARGS; } } } back[lgt] = '\0'; } else { if(ecp) { *ecp = DK_ERR_NOMEM; } } } } else { if(ecp) { *ecp = DK_ERR_INVALID_ARGS; } } return back; } char * dkenc_str_bits82utf8 DK_P1(char *,s) { int me; /* math error indicator */ dk_ubyte buffer[16]; /* 7 would be sufficient */ char *back = NULL; char c, *cptr; size_t lgt, lgtnew; dk_ubyte ub; dk_udword uw; if(s) { cptr = s; lgt = 1; me = 0; while(*cptr) { c = *cptr; ub = (dk_ubyte)c; uw = (dk_udword)ub; lgtnew = lgt + dkenc_uc2utf8(uw, buffer, 16); if(lgtnew >= lgt) { lgt = lgtnew; } else { me = 1; } cptr++; } if(!me) { back = dk_new(char,lgt); if(back) { size_t i, ni; ni = 0; cptr = s; while(*cptr) { c = *cptr; ub = (dk_ubyte)c; uw = (dk_udword)ub; lgtnew = dkenc_uc2utf8(uw, buffer, 16); for(i = 0; i < lgtnew; i++) { back[ni + i] = buffer[i]; } ni += lgtnew; cptr++; } back[ni] = '\0'; } } } return back; } size_t dkenc_size_bin_to_a85 DK_P1(size_t,s) { size_t back = 0; int ec = 0; unsigned long ul1, ul2, ul3; ul1 = (unsigned long)s; ul2 = ul1 % 4UL; ul3 = ul1 / 4UL; if(ul2) ul2++; /* for last incomplete block */ ul1 = dkma_add_ulong_ok( dkma_mul_ulong_ok(ul3, 5UL, &ec), ul2, &ec ); /* add 25 percent */ ul1++; /* final 0x00 byte for string */ back = (size_t)ul1; if(ec) back = 0; /* error checking */ if((unsigned long)back != ul1) back = 0; return back; } /** Convert binary data to ASCII-85 encoded string. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. */ static void do_bin_to_ra85 DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { register char *mysp; register unsigned char *mydp; register unsigned long v; register size_t i; register short vused; mydp = (unsigned char *)dp; mysp = sp; v = 0UL; vused = 0; for(i = 0; i < ss; i++) { switch(vused++) { case 3: { v |= ((((unsigned long)((unsigned char)(*(mysp++)))) << 24) & 0xFF000000UL); } break; case 2: { v |= ((((unsigned long)((unsigned char)(*(mysp++)))) << 16) & 0x00FF0000UL); } break; case 1: { v |= ((((unsigned long)((unsigned char)(*(mysp++)))) << 8) & 0x0000FF00UL); } break; default: { v |= ((((unsigned long)((unsigned char)(*(mysp++)))) ) & last_byte); } break; } if(vused >= 4) { *(mydp++) = (unsigned char)((v % 85UL) + 33UL); v = v / 85UL; *(mydp++) = (unsigned char)((v % 85UL) + 33UL); v = v / 85UL; *(mydp++) = (unsigned char)((v % 85UL) + 33UL); v = v / 85UL; *(mydp++) = (unsigned char)((v % 85UL) + 33UL); v = v / 85UL; *(mydp++) = (unsigned char)((v % 85UL) + 33UL); vused = 0; v = 0UL; } } if(vused) { vused++; while(vused--) { *(mydp++) = (unsigned char)((v % 85UL) + 33UL); v = v / 85UL; } } *mydp = '\0'; } int dkenc_bin_to_ra85 DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { int back = 0; size_t needed_size; if((dp) && (sp) && (ds) && (ss)) { needed_size = dkenc_size_bin_to_a85(ss); if(needed_size) { if(ds >= needed_size) { do_bin_to_ra85(dp, ds, sp, ss); back = 1; } } } return back; } size_t dkenc_size_a85_to_bin DK_P1(size_t,s) { size_t back = 0; unsigned long ul1, ul2, ul3; ul1 = (unsigned long)s; ul2 = ul1 % 5UL; ul3 = ul1 / 5UL; ul1 = 4UL * ul3 + ul2; back = (size_t)ul1; return back; } /** Check whether a character is from the ASCII-85 charset. @param c Character to check. @return 1 on success, 0 on error. */ static int is_a85 DK_P1(char,c) { int back = 1; if((int)c < 33) { back = 0; } else { if((int)c > 117) { back = 0; } } return back; } /** Convert reverse ASCII-85 encoded data to binary data. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. @return Number of binary bytes produced. */ static size_t do_ra85_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { size_t back = 0; unsigned char *mydp; char *mysp; unsigned long v; short vused; size_t i; mydp = (unsigned char *)dp; mysp = sp; v = 0UL; vused = 0; for(i = 0; i < ss; i++) { if(is_a85(*mysp)) { v += f2[vused++] * ((((unsigned long)((unsigned char)(*mysp))) & last_byte) - 33UL); if(vused >= 5) { *(mydp++) = (unsigned char)(v & last_byte); *(mydp++) = (unsigned char)((v >> 8) & last_byte); *(mydp++) = (unsigned char)((v >> 16) & last_byte); *(mydp++) = (unsigned char)((v >> 24) & last_byte); back += 4; v = 0UL; vused = 0; } } mysp++; } if(vused) { vused--; while(vused--) { *(mydp++) = (unsigned char)(v & last_byte); back++; v = v >> 8; } } return back; } size_t dkenc_ra85_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { size_t back = 0; size_t needed_size; if((dp) && (sp) && (ds) && (ss)) { needed_size = dkenc_size_a85_to_bin(ss); if(needed_size) { if(ds >= needed_size) { back = do_ra85_to_bin(dp, ds, sp, ss); } } } return back; } size_t dkenc_ra85string_to_bin DK_P3(char *,dp, size_t,ds, char *,sp) { size_t back = 0; if(sp) { back = dkenc_ra85_to_bin(dp, ds, sp, strlen(sp)); } return back; } /** Convert binary data to ASCII-85 string. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. */ static void do_bin_to_a85 DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { register unsigned char *mydp; register unsigned char *mysp; register unsigned long v; register short vused; register short addval; register size_t i; mydp = (unsigned char *)dp; mysp = (unsigned char *)sp; v = 0UL; vused = 0; for(i = 0; i < ss; i++) { switch(vused) { case 3: { v |= ( ((unsigned long)(*(mysp++))) & 0x000000FFUL); } break; case 2: { v |= ((((unsigned long)(*(mysp++))) << 8) & 0x0000FF00UL); } break; case 1: { v |= ((((unsigned long)(*(mysp++))) << 16) & 0x00FF0000UL); } break; default: { v |= ((((unsigned long)(*(mysp++))) << 24) & 0xFF000000UL); } break; } if(++vused >= 4) { vused = 5; while(vused--) { *(mydp++) = (unsigned char)(33UL + v / f2[vused]); v = v % f2[vused]; } v = 0UL; vused = 0; } } if(vused) { vused++; addval = 5 - vused; while(vused--) { *(mydp++) = (unsigned char)(33UL + v / f2[vused + addval]); v = v % f2[vused + addval]; } } *mydp = '\0'; } int dkenc_bin_to_a85 DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { int back = 0; size_t needed_size; if((dp) && (sp) && (ds) && (ss)) { needed_size = dkenc_size_bin_to_a85(ss); if(needed_size) { if(ds >= needed_size) { do_bin_to_a85(dp, ds, sp, ss); back = 1; } } } return back; } /** Convert ASCII-85 encoded data to binary data. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. @return Number of binary bytes produced. */ static size_t do_a85_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { register size_t back = 0; register unsigned char *mydp; register unsigned char *mysp; register unsigned long v; register short vused; register size_t i; unsigned long u1, u2, u3; mydp = (unsigned char *)dp; mysp = (unsigned char *)sp; v = 0UL; vused = 0; for(i = 0; i < ss; i++) { if(*mysp) { if(is_a85(*mysp)) { v += f2[4 - vused] * ((((unsigned long)(*mysp)) & 0x000000FFUL) - 33UL); } vused++; if(vused >= 5) { *(mydp++) = (unsigned char)((v >> 24) & 0x000000FFUL); back++; *(mydp++) = (unsigned char)((v >> 16) & 0x000000FFUL); back++; *(mydp++) = (unsigned char)((v >> 8) & 0x000000FFUL); back++; *(mydp++) = (unsigned char)( v & 0x000000FFUL); back++; v = 0UL; vused = 0; } } mysp++; } if(vused) { u1 = (v >> 24) & 0x000000FFUL; u2 = (v >> 16) & 0x000000FFUL; u3 = (v >> 8) & 0x000000FFUL; switch(vused) { case 2: { if(v & 0x00FFFFFFUL) { u1++; if(u1 >= 256UL) u1 = 0UL; } *(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++; } break; case 3: { if(v & 0x0000FFFFUL) { u2++; if(u2 >= 256UL) { u2 = 0UL; u1++; if(u1 >= 256UL) u1 = 0UL; } } *(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++; *(mydp++) = (unsigned char)(u2 & 0x000000FFUL); back++; } break; case 4: { if(v & 0x000000FFUL) { u3++; if(u3 >= 256UL) { u3 = 0UL; u2++; if(u2 >= 256UL) { u2 = 0UL; u1++; if(u1 >= 256UL) u1 = 0UL; } } } *(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++; *(mydp++) = (unsigned char)(u2 & 0x000000FFUL); back++; *(mydp++) = (unsigned char)(u3 & 0x000000FFUL); back++; } break; } } return back; } size_t dkenc_a85_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { size_t back = 0; size_t needed_size; if((dp) && (sp) && (ds) && (ss)) { needed_size = dkenc_size_a85_to_bin(ss); if(needed_size) { if(ds >= needed_size) { back = do_a85_to_bin(dp, ds, sp, ss); } } } return back; } size_t dkenc_a85string_to_bin DK_P3(char *,dp, size_t,ds, char *,sp) { size_t back = 0; if(sp) { back = dkenc_a85_to_bin(dp, ds, sp, strlen(sp)); } return back; } size_t dkenc_size_bin_to_hex DK_P1(size_t,s) { size_t back = 0; int ec = 0; unsigned long ul1; ul1 = (unsigned long)s; ul1 = dkma_mul_ulong_ok(ul1, 2UL, &ec); ul1 = dkma_add_ulong_ok(ul1, 1UL, &ec); back = (size_t)ul1; if(ec) back = 0; if((unsigned long)back != ul1) back = 0; return back; } size_t dkenc_size_hex_to_bin DK_P1(size_t,s) { size_t back; back = s / 2; back++; return back; } /** Digits used to show hexadecimal characters. */ static char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\0' }; /** Get higher half-byte from character. @param c Source character. @return Higher half-byte of \a c. */ static char high_nibble_hex DK_P1(char,c) { char back; back = hex_digits[ (((unsigned short)c) >> 4) & 0x000FU ]; return back; } /** Get lower half-byte from character. @param c Source character. @return Lower half-byte of \a c. */ static char low_nibble_hex DK_P1(char,c) { char back; back = hex_digits[ ((unsigned short)c) & 0x000FU ]; return back; } /** Convert binary data to hexadecimal string. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. */ static void do_bin_to_hex DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { register char *mydp; register char *mysp; register size_t i; mydp = dp; mysp = sp; for(i = 0; i < ss; i++) { *(mydp++) = high_nibble_hex(*mysp); *(mydp++) = low_nibble_hex(*(mysp++)); } *mydp = '\0'; } int dkenc_bin_to_hex DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { int back = 0; size_t needed_bytes; if((dp) && (ds) && (sp) && (ss)) { needed_bytes = dkenc_size_bin_to_hex(ss); if(needed_bytes) { if(ds >= needed_bytes) { do_bin_to_hex(dp, ds, sp, ss); back = 1; } } } return back; } /** Convert hexadecimal data to binary data. @param dp Destination pointer. @param ds Destination size. @param sp Source pointer. @param ss Source size. @return Number of bytes created in destination. */ static size_t do_hex_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { register size_t back = 0; register char *mysp; register unsigned char *mydp; register unsigned char v; register short int vused; register size_t i; mydp = (unsigned char *)dp; mysp = sp; v = 0x00; vused = 0U; for(i = 0; i < ss; i++) { switch(*mysp) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'A': case 'b': case 'B': case 'c': case 'C': case 'd': case 'D': case 'e': case 'E': case 'f': case 'F': { if(vused) { switch(*mysp) { case '0': { v |= 0x00; } break; case '1': { v |= 0x01; } break; case '2': { v |= 0x02; } break; case '3': { v |= 0x03; } break; case '4': { v |= 0x04; } break; case '5': { v |= 0x05; } break; case '6': { v |= 0x06; } break; case '7': { v |= 0x07; } break; case '8': { v |= 0x08; } break; case '9': { v |= 0x09; } break; case 'a': { v |= 0x0A; } break; case 'A': { v |= 0x0A; } break; case 'b': { v |= 0x0B; } break; case 'B': { v |= 0x0B; } break; case 'c': { v |= 0x0C; } break; case 'C': { v |= 0x0C; } break; case 'd': { v |= 0x0D; } break; case 'D': { v |= 0x0D; } break; case 'e': { v |= 0x0E; } break; case 'E': { v |= 0x0E; } break; case 'f': { v |= 0x0F; } break; case 'F': { v |= 0x0F; } break; } *(mydp++) = v; back++; v = 0; vused = 0U; } else { switch(*mysp) { case '0': { v = 0x00; } break; case '1': { v = 0x10; } break; case '2': { v = 0x20; } break; case '3': { v = 0x30; } break; case '4': { v = 0x40; } break; case '5': { v = 0x50; } break; case '6': { v = 0x60; } break; case '7': { v = 0x70; } break; case '8': { v = 0x80; } break; case '9': { v = 0x90; } break; case 'a': { v = 0xA0; } break; case 'A': { v = 0xA0; } break; case 'b': { v = 0xB0; } break; case 'B': { v = 0xB0; } break; case 'c': { v = 0xC0; } break; case 'C': { v = 0xC0; } break; case 'd': { v = 0xD0; } break; case 'D': { v = 0xD0; } break; case 'e': { v = 0xE0; } break; case 'E': { v = 0xE0; } break; case 'f': { v = 0xF0; } break; case 'F': { v = 0xF0; } break; } vused = 1U; } } break; } mysp++; } if(vused) { *mydp = v; back++; } return back; } size_t dkenc_hex_to_bin DK_P4(char *,dp, size_t,ds, char *,sp, size_t,ss) { size_t back = 0; size_t needed_bytes; if((dp) && (ds) && (sp) && (ss)) { needed_bytes = dkenc_size_hex_to_bin(ss); if(needed_bytes) { if(ds >= needed_bytes) { back = do_hex_to_bin(dp, ds, sp, ss); } } } return back; } size_t dkenc_hexstring_to_bin DK_P3(char *,dp, size_t,ds, char *,sp) { size_t back = 0; if(sp) { back = dkenc_hex_to_bin(dp, ds, sp, strlen(sp)); } return back; } size_t dkenc_size_hexstring_to_bin DK_P1(char *,s) { size_t back = 0; if(s) { back = strlen(s); back = dkenc_size_hex_to_bin(back); } return back; } size_t dkenc_size_a85string_to_bin DK_P1(char *,s) { size_t back = 0; if(s) { back = strlen(s); back = dkenc_size_a85_to_bin(back); } return back; }