1d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* vi: set expandtab shiftwidth=4 tabstop=4: */
3d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/**
4d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * \file
5d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * <PRE>
6d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * MODP_B64 - High performance base64 encoder/decoder
7d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * Version 1.3 -- 17-Mar-2006
8d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * http://modp.com/release/base64
9d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
10d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * Copyright &copy; 2005, 2006  Nick Galbreath -- nickg [at] modp [dot] com
11d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * All rights reserved.
12d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
13d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * Redistribution and use in source and binary forms, with or without
14d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * modification, are permitted provided that the following conditions are
15d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * met:
16d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
17d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   Redistributions of source code must retain the above copyright
18d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   notice, this list of conditions and the following disclaimer.
19d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
20d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   Redistributions in binary form must reproduce the above copyright
21d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   notice, this list of conditions and the following disclaimer in the
22d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   documentation and/or other materials provided with the distribution.
23d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
24d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   Neither the name of the modp.com nor the names of its
25d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   contributors may be used to endorse or promote products derived from
26d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *   this software without specific prior written permission.
27d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
28d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott *
40d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * This is the standard "new" BSD license:
41d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * http://www.opensource.org/licenses/bsd-license.php
42d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * </PRE>
43d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott */
44d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
45d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* public header */
46d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#include "modp_b64.h"
47d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
48d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/*
49d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * If you are ripping this out of the library, comment out the next
50d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * line and uncomment the next lines as approrpiate
51d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott */
52d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott//#include "config.h"
53d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
54d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* if on motoral, sun, ibm; uncomment this */
55d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* #define WORDS_BIGENDIAN 1 */
56d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* else for Intel, Amd; uncomment this */
57d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/* #undef WORDS_BIGENDIAN */
58d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
59d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#include "modp_b64_data.h"
60d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
61d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#define BADCHAR 0x01FFFFFF
62d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
63d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/**
64d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * you can control if we use padding by commenting out this
65d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * next line.  However, I highly recommend you use padding and not
66d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * using it should only be for compatability with a 3rd party.
67d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * Also, 'no padding' is not tested!
68d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott */
69d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#define DOPAD 1
70d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
71d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott/*
72d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * if we aren't doing padding
73d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott * set the pad character to NULL
74d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott */
75d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#ifndef DOPAD
76d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#undef CHARPAD
77d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#define CHARPAD '\0'
78d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#endif
79d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
80d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scottint modp_b64_encode(char* dest, const char* str, int len)
81d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott{
82d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int i;
83d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint8_t* p = (uint8_t*) dest;
84d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
85d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    /* unsigned here is important! */
86d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint8_t t1, t2, t3;
87d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
88d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    for (i = 0; i < len - 2; i += 3) {
89d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        t1 = str[i]; t2 = str[i+1]; t3 = str[i+2];
90d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e0[t1];
91d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
92d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
93d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e2[t3];
94d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
95d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
96d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    switch (len - i) {
97d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 0:
98d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
99d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 1:
100d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        t1 = str[i];
101d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e0[t1];
102d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e1[(t1 & 0x03) << 4];
103d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = CHARPAD;
104d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = CHARPAD;
105d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
106d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    default: /* case 2 */
107d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        t1 = str[i]; t2 = str[i+1];
108d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e0[t1];
109d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
110d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = e2[(t2 & 0x0F) << 2];
111d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = CHARPAD;
112d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
113d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
114d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    *p = '\0';
115d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    return p - (uint8_t*)dest;
116d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott}
117d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
118d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#ifdef WORDS_BIGENDIAN   /* BIG ENDIAN -- SUN / IBM / MOTOROLA */
119d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scottint modp_b64_decode(char* dest, const char* src, int len)
120d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott{
121d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (len == 0) return 0;
122d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
123d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#ifdef DOPAD
124d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    /* if padding is used, then the message must be at least
125d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott       4 chars and be a multiple of 4.
126d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott       there can be at most 2 pad chars at the end */
127d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (len < 4 || (len % 4 != 0)) return -1;
128d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (src[len-1] == CHARPAD) {
129d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        len--;
130d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (src[len -1] == CHARPAD) {
131d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            len--;
132d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        }
133d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
134d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#endif  /* DOPAD */
135d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
136d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int i;
137d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int leftover = len % 4;
138d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int chunks = (leftover == 0) ? len / 4 - 1 : len /4;
139d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
140d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint8_t* p = (uint8_t*) dest;
141d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t x = 0;
142d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t* destInt = (uint32_t*) p;
143d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t* srcInt = (uint32_t*) src;
144d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t y = *srcInt++;
145d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    for (i = 0; i < chunks; ++i) {
146d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
147d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d2[y >> 8 & 0xff] | d3[y & 0xff];
148d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
149d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (x >= BADCHAR)  return -1;
150d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *destInt = x << 8;
151d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        p += 3;
152d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        destInt = (uint32_t*)p;
153d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        y = *srcInt++;
154d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
155d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
156d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    switch (leftover) {
157d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 0:
158d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
159d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d2[y >>  8 & 0xff] | d3[y & 0xff];
160d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (x >= BADCHAR)  return -1;
161d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = ((uint8_t*)&x)[1];
162d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = ((uint8_t*)&x)[2];
163d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p = ((uint8_t*)&x)[3];
164d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        return (chunks+1)*3;
165d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 1:
166d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d3[y >> 24];
167d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p =  (uint8_t)x;
168d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
169d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 2:
170d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d3[y >> 24] *64 + d3[(y >> 16) & 0xff];
171d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p =  (uint8_t)(x >> 4);
172d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
173d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    default:  /* case 3 */
174d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = (d3[y >> 24] *64 + d3[(y >> 16) & 0xff])*64 +
175d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d3[(y >> 8) & 0xff];
176d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ = (uint8_t) (x >> 10);
177d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p = (uint8_t) (x >> 2);
178d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
179d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
180d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
181d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (x >= BADCHAR) return -1;
182d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    return 3*chunks + (6*leftover)/8;
183d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott}
184d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
185d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#else /* LITTLE  ENDIAN -- INTEL AND FRIENDS */
186d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
187d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scottint modp_b64_decode(char* dest, const char* src, int len)
188d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott{
189d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (len == 0) return 0;
190d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
191d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#ifdef DOPAD
192d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    /*
193d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott     * if padding is used, then the message must be at least
194d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott     * 4 chars and be a multiple of 4
195d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott     */
196d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (len < 4 || (len % 4 != 0)) return -1; /* error */
197d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    /* there can be at most 2 pad chars at the end */
198d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (src[len-1] == CHARPAD) {
199d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        len--;
200d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (src[len -1] == CHARPAD) {
201d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            len--;
202d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        }
203d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
204d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#endif
205d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
206d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int i;
207d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int leftover = len % 4;
208d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    int chunks = (leftover == 0) ? len / 4 - 1 : len /4;
209d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
210d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint8_t* p = (uint8_t*)dest;
211d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t x = 0;
212d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t* destInt = (uint32_t*) p;
213d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t* srcInt = (uint32_t*) src;
214d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    uint32_t y = *srcInt++;
215d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    for (i = 0; i < chunks; ++i) {
216d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y & 0xff] |
217d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d1[(y >> 8) & 0xff] |
218d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d2[(y >> 16) & 0xff] |
219d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d3[(y >> 24) & 0xff];
220d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
221d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (x >= BADCHAR) return -1;
222d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *destInt = x ;
223d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        p += 3;
224d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        destInt = (uint32_t*)p;
225d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        y = *srcInt++;}
226d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
227d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
228d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    switch (leftover) {
229d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 0:
230d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y & 0xff] |
231d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d1[(y >> 8) & 0xff] |
232d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d2[(y >> 16) & 0xff] |
233d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d3[(y >> 24) & 0xff];
234d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
235d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        if (x >= BADCHAR) return -1;
236d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ =  ((uint8_t*)(&x))[0];
237d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ =  ((uint8_t*)(&x))[1];
238d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p =    ((uint8_t*)(&x))[2];
239d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        return (chunks+1)*3;
240d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
241d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 1:  /* with padding this is an impossible case */
242d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y & 0xff];
243d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p = *((uint8_t*)(&x)); // i.e. first char/byte in int
244d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
245d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    case 2: // * case 2, 1  output byte */
246d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y & 0xff] | d1[y >> 8 & 0xff];
247d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p = *((uint8_t*)(&x)); // i.e. first char
248d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
249d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    default: /* case 3, 2 output bytes */
250d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        x = d0[y & 0xff] |
251d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d1[y >> 8 & 0xff ] |
252d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott            d2[y >> 16 & 0xff];  /* 0x3c */
253d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p++ =  ((uint8_t*)(&x))[0];
254d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        *p =  ((uint8_t*)(&x))[1];
255d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott        break;
256d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    }
257d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
258d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    if (x >= BADCHAR) return -1;
259d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
260d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott    return 3*chunks + (6*leftover)/8;
261d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott}
262d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott
263d9f0c9bcce7092bf92cab485981630bd74307831Patrick Scott#endif  /* if bigendian / else / endif */
264