]> sjero.net Git - linphone/blob - linphone/oRTP/src/b64.c
08b0ed3e6254b19af5048a2137125efdf25deec2
[linphone] / linphone / oRTP / src / b64.c
1 /* /////////////////////////////////////////////////////////////////////////////\r
2  * File:        b64.c\r
3  *\r
4  * Purpose:     Implementation file for the b64 library\r
5  *\r
6  * Created:     18th October 2004\r
7  * Updated:     3rd May 2008\r
8  *\r
9  * Home:        http://synesis.com.au/software/\r
10  *\r
11  * Copyright (c) 2004-2008, Matthew Wilson and Synesis Software\r
12  * All rights reserved.\r
13  *\r
14  * Redistribution and use in source and binary forms, with or without \r
15  * modification, are permitted provided that the following conditions are met:\r
16  *\r
17  * - Redistributions of source code must retain the above copyright notice, this\r
18  *   list of conditions and the following disclaimer. \r
19  * - Redistributions in binary form must reproduce the above copyright notice,\r
20  *   this list of conditions and the following disclaimer in the documentation\r
21  *   and/or other materials provided with the distribution.\r
22  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of\r
23  *   any contributors may be used to endorse or promote products derived from\r
24  *   this software without specific prior written permission.\r
25  *\r
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
36  * POSSIBILITY OF SUCH DAMAGE.\r
37  *\r
38  * ////////////////////////////////////////////////////////////////////////// */\r
39 \r
40 \r
41 /** \file b64.c Implementation file for the b64 library\r
42  */\r
43 \r
44 /* /////////////////////////////////////////////////////////////////////////////\r
45  * Version information\r
46  */\r
47 \r
48 #ifndef B64_DOCUMENTATION_SKIP_SECTION\r
49 # define B64_VER_C_B64_MAJOR    1\r
50 # define B64_VER_C_B64_MINOR    2\r
51 # define B64_VER_C_B64_REVISION 3\r
52 # define B64_VER_C_B64_EDIT     17\r
53 #endif /* !B64_DOCUMENTATION_SKIP_SECTION */\r
54 \r
55 /* /////////////////////////////////////////////////////////////////////////////\r
56  * Includes\r
57  */\r
58 \r
59 #include "ortp/b64.h"\r
60 \r
61 #include <assert.h>\r
62 #include <string.h>\r
63 #include "ortp/port.h"\r
64 /* /////////////////////////////////////////////////////////////////////////////\r
65  * Constants and definitions\r
66  */\r
67 \r
68 #ifndef B64_DOCUMENTATION_SKIP_SECTION\r
69 # define NUM_PLAIN_DATA_BYTES        (3)\r
70 # define NUM_ENCODED_DATA_BYTES      (4)\r
71 #endif /* !B64_DOCUMENTATION_SKIP_SECTION */\r
72 \r
73 /* /////////////////////////////////////////////////////////////////////////////\r
74  * Macros\r
75  */\r
76 \r
77 #ifndef NUM_ELEMENTS\r
78 # define NUM_ELEMENTS(x)        (sizeof(x) / sizeof(x[0]))\r
79 #endif /* !NUM_ELEMENTS */\r
80 \r
81 /* /////////////////////////////////////////////////////////////////////////////\r
82  * Warnings\r
83  */\r
84 \r
85 #if defined(_MSC_VER) && \\r
86     _MSC_VER < 1000\r
87 # pragma warning(disable : 4705)\r
88 #endif /* _MSC_VER < 1000 */\r
89 \r
90 /* /////////////////////////////////////////////////////////////////////////////\r
91  * Data\r
92  */\r
93 \r
94 static const char           b64_chars[] =   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
95 \r
96 static const signed char    b64_indexes[]   =   \r
97 {\r
98     /* 0 - 31 / 0x00 - 0x1f */\r
99         -1, -1, -1, -1, -1, -1, -1, -1  \r
100     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
101     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
102     ,   -1, -1, -1, -1, -1, -1, -1, -1\r
103     /* 32 - 63 / 0x20 - 0x3f */\r
104     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
105     ,   -1, -1, -1, 62, -1, -1, -1, 63  /* ... , '+', ... '/' */\r
106     ,   52, 53, 54, 55, 56, 57, 58, 59  /* '0' - '7' */\r
107     ,   60, 61, -1, -1, -1, -1, -1, -1  /* '8', '9', ... */\r
108     /* 64 - 95 / 0x40 - 0x5f */\r
109     ,   -1, 0,  1,  2,  3,  4,  5,  6   /* ..., 'A' - 'G' */\r
110     ,   7,  8,  9,  10, 11, 12, 13, 14  /* 'H' - 'O' */\r
111     ,   15, 16, 17, 18, 19, 20, 21, 22  /* 'P' - 'W' */\r
112     ,   23, 24, 25, -1, -1, -1, -1, -1  /* 'X', 'Y', 'Z', ... */\r
113     /* 96 - 127 / 0x60 - 0x7f */\r
114     ,   -1, 26, 27, 28, 29, 30, 31, 32  /* ..., 'a' - 'g' */\r
115     ,   33, 34, 35, 36, 37, 38, 39, 40  /* 'h' - 'o' */\r
116     ,   41, 42, 43, 44, 45, 46, 47, 48  /* 'p' - 'w' */\r
117     ,   49, 50, 51, -1, -1, -1, -1, -1  /* 'x', 'y', 'z', ... */\r
118 \r
119     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
120     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
121     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
122     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
123 \r
124     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
125     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
126     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
127     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
128 \r
129     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
130     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
131     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
132     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
133 \r
134     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
135     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
136     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
137     ,   -1, -1, -1, -1, -1, -1, -1, -1  \r
138 };\r
139 \r
140 /* /////////////////////////////////////////////////////////////////////////////\r
141  * Helper functions\r
142  */\r
143 \r
144 /** This function reads in 3 bytes at a time, and translates them into 4\r
145  * characters.\r
146  */\r
147 static size_t b64_encode_(  unsigned char const *src\r
148                         ,   size_t              srcSize\r
149                         ,   char *const         dest\r
150                         ,   size_t              destLen\r
151                         ,   unsigned            lineLen\r
152                         ,   B64_RC              *rc)\r
153 {\r
154     size_t total = ((srcSize + (NUM_PLAIN_DATA_BYTES - 1)) / NUM_PLAIN_DATA_BYTES) * NUM_ENCODED_DATA_BYTES;\r
155 \r
156     assert(NULL != rc);\r
157     *rc = B64_RC_OK;\r
158 \r
159     if(lineLen > 0)\r
160     {\r
161         size_t numLines = (total + (lineLen - 1)) / lineLen;\r
162 \r
163         total += 2 * (numLines - 1);\r
164     }\r
165 \r
166     if(NULL == dest)\r
167     {\r
168         return total;\r
169     }\r
170     else if(destLen < total)\r
171     {\r
172         *rc = B64_RC_INSUFFICIENT_BUFFER;\r
173 \r
174         return 0;\r
175     }\r
176     else\r
177     {\r
178         char    *p      =   dest;\r
179         char    *end    =   dest + destLen;\r
180         size_t  len     =   0;\r
181 \r
182         for(; NUM_PLAIN_DATA_BYTES <= srcSize; srcSize -= NUM_PLAIN_DATA_BYTES)\r
183         {\r
184             char    characters[NUM_ENCODED_DATA_BYTES];\r
185 \r
186             /* \r
187              * \r
188              * |       0       |       1       |       2       |\r
189              *\r
190              * |               |               |               |\r
191              * |       |       |       |       |       |       |\r
192              * |   |   |   |   |   |   |   |   |   |   |   |   |\r
193              * | | | | | | | | | | | | | | | | | | | | | | | | |\r
194              * \r
195              * |     0     |     1     |     2     |     3     |\r
196              * \r
197              */\r
198 \r
199             /* characters[0] is the 6 left-most bits of src[0] */\r
200             characters[0] = (char)((src[0] & 0xfc) >> 2);\r
201             /* characters[0] is the right-most 2 bits of src[0] and the left-most 4 bits of src[1] */\r
202             characters[1] = (char)(((src[0] & 0x03) << 4) + ((src[1] & 0xf0) >> 4));\r
203             /* characters[0] is the right-most 4 bits of src[1] and the 2 left-most bits of src[2] */\r
204             characters[2] = (char)(((src[1] & 0x0f) << 2) + ((src[2] & 0xc0) >> 6));\r
205             /* characters[3] is the right-most 6 bits of src[2] */\r
206             characters[3] = (char)(src[2] & 0x3f);\r
207 \r
208 #ifndef __WATCOMC__\r
209             assert(characters[0] >= 0 && characters[0] < 64);\r
210             assert(characters[1] >= 0 && characters[1] < 64);\r
211             assert(characters[2] >= 0 && characters[2] < 64);\r
212             assert(characters[3] >= 0 && characters[3] < 64);\r
213 #endif /* __WATCOMC__ */\r
214 \r
215             src += NUM_PLAIN_DATA_BYTES;\r
216             *p++ = b64_chars[(unsigned char)characters[0]];\r
217             assert(NULL != strchr(b64_chars, *(p-1)));\r
218             ++len;\r
219             assert(len != lineLen);\r
220 \r
221             *p++ = b64_chars[(unsigned char)characters[1]];\r
222             assert(NULL != strchr(b64_chars, *(p-1)));\r
223             ++len;\r
224             assert(len != lineLen);\r
225 \r
226             *p++ = b64_chars[(unsigned char)characters[2]];\r
227             assert(NULL != strchr(b64_chars, *(p-1)));\r
228             ++len;\r
229             assert(len != lineLen);\r
230 \r
231             *p++ = b64_chars[(unsigned char)characters[3]];\r
232             assert(NULL != strchr(b64_chars, *(p-1)));\r
233 \r
234             if( ++len == lineLen &&\r
235                 p != end)\r
236             {\r
237                 *p++ = '\r';\r
238                 *p++ = '\n';\r
239                 len = 0;\r
240             }\r
241         }\r
242 \r
243         if(0 != srcSize)\r
244         {\r
245             /* Deal with the overspill, by boosting it up to three bytes (using 0s)\r
246              * and then appending '=' for any missing characters.\r
247              *\r
248              * This is done into a temporary buffer, so we can call ourselves and\r
249              * have the output continue to be written direct to the destination.\r
250              */\r
251 \r
252             unsigned char   dummy[NUM_PLAIN_DATA_BYTES];\r
253             size_t          i;\r
254 \r
255             for(i = 0; i < srcSize; ++i)\r
256             {\r
257                 dummy[i] = *src++;\r
258             }\r
259 \r
260             for(; i < NUM_PLAIN_DATA_BYTES; ++i)\r
261             {\r
262                 dummy[i] = '\0';\r
263             }\r
264 \r
265             b64_encode_(&dummy[0], NUM_PLAIN_DATA_BYTES, p, NUM_ENCODED_DATA_BYTES * (1 + 2), 0, rc);\r
266 \r
267             for(p += 1 + srcSize; srcSize++ < NUM_PLAIN_DATA_BYTES; )\r
268             {\r
269                 *p++ = '=';\r
270             }\r
271         }\r
272 \r
273         return total;\r
274     }\r
275 }\r
276 \r
277 /** This function reads in a character string in 4-character chunks, and writes \r
278  * out the converted form in 3-byte chunks to the destination.\r
279  */\r
280 static size_t b64_decode_(  char const      *src\r
281                         ,   size_t          srcLen\r
282                         ,   unsigned char   *dest\r
283                         ,   size_t          destSize\r
284                         ,   unsigned        flags\r
285                         ,   char const      **badChar\r
286                         ,   B64_RC          *rc)\r
287 {\r
288     const size_t    wholeChunks     =   (srcLen / NUM_ENCODED_DATA_BYTES);\r
289     const size_t    remainderBytes  =   (srcLen % NUM_ENCODED_DATA_BYTES);\r
290     size_t          maxTotal        =   (wholeChunks + (0 != remainderBytes)) * NUM_PLAIN_DATA_BYTES;\r
291     unsigned char   *dest_          =   dest;\r
292 \r
293     ((void)remainderBytes);\r
294 \r
295     assert(NULL != badChar);\r
296     assert(NULL != rc);\r
297 \r
298     *badChar    =   NULL;\r
299     *rc         =   B64_RC_OK;\r
300 \r
301     if(NULL == dest)\r
302     {\r
303         return maxTotal;\r
304     }\r
305     else if(destSize < maxTotal)\r
306     {\r
307         *rc = B64_RC_INSUFFICIENT_BUFFER;\r
308 \r
309         return 0;\r
310     }\r
311     else\r
312     {\r
313         /* Now we iterate through the src, collecting together four characters\r
314          * at a time from the Base-64 alphabet, until the end-point is reached.\r
315          *\r
316          * \r
317          */\r
318 \r
319         char const          *begin      =   src;\r
320         char const  *const  end         =   begin + srcLen;\r
321         size_t              currIndex   =   0;\r
322         size_t              numPads     =   0;\r
323         signed char         indexes[NUM_ENCODED_DATA_BYTES];    /* 4 */\r
324 \r
325         for(; begin != end; ++begin)\r
326         {\r
327             const char  ch  =   *begin;\r
328 \r
329             if('=' == ch)\r
330             {\r
331                 assert(currIndex < NUM_ENCODED_DATA_BYTES);\r
332 \r
333                 indexes[currIndex++] = '\0';\r
334 \r
335                 ++numPads;\r
336             }\r
337             else\r
338             {\r
339                 /* NOTE: Had to rename 'index' to 'ix', due to name clash with GCC on 64-bit Linux. */\r
340                 signed char ix   =   b64_indexes[(unsigned char)ch];\r
341 \r
342                 if(-1 == ix)\r
343                 {\r
344                     switch(ch)\r
345                     {\r
346                         case    ' ':\r
347                         case    '\t':\r
348                         case    '\b':\r
349                         case    '\v':\r
350                             if(B64_F_STOP_ON_UNEXPECTED_WS & flags)\r
351                             {\r
352                                 *rc         =   B64_RC_DATA_ERROR;\r
353                                 *badChar    =   begin;\r
354                                 return 0;\r
355                             }\r
356                             else\r
357                             {\r
358                                 /* Fall through */\r
359                             }\r
360                         case    '\r':\r
361                         case    '\n':\r
362                             continue;\r
363                         default:\r
364                             if(B64_F_STOP_ON_UNKNOWN_CHAR & flags)\r
365                             {\r
366                                 *rc         =   B64_RC_DATA_ERROR;\r
367                                 *badChar    =   begin;\r
368                                 return 0;\r
369                             }\r
370                             else\r
371                             {\r
372                                 continue;\r
373                             }\r
374                     }\r
375                 }\r
376                 else\r
377                 {\r
378                     numPads = 0;\r
379 \r
380                     assert(currIndex < NUM_ENCODED_DATA_BYTES);\r
381 \r
382                     indexes[currIndex++] = ix;\r
383                 }\r
384             }\r
385 \r
386             if(NUM_ENCODED_DATA_BYTES == currIndex)\r
387             {\r
388                 unsigned char   bytes[NUM_PLAIN_DATA_BYTES];        /* 3 */\r
389 \r
390                 bytes[0] = (unsigned char)((indexes[0] << 2) + ((indexes[1] & 0x30) >> 4));\r
391 \r
392                 currIndex = 0;\r
393 \r
394                 *dest++ = bytes[0];\r
395                 if(2 != numPads)\r
396                 {\r
397                     bytes[1] = (unsigned char)(((indexes[1] & 0xf) << 4) + ((indexes[2] & 0x3c) >> 2));\r
398 \r
399                     *dest++ = bytes[1];\r
400 \r
401                     if(1 != numPads)\r
402                     {\r
403                         bytes[2] = (unsigned char)(((indexes[2] & 0x3) << 6) + indexes[3]);\r
404 \r
405                         *dest++ = bytes[2];\r
406                     }\r
407                 }\r
408                 if(0 != numPads)\r
409                 {\r
410                     break;\r
411                 }\r
412             }\r
413         }\r
414 \r
415         return (size_t)(dest - dest_);\r
416     }\r
417 }\r
418 \r
419 /* /////////////////////////////////////////////////////////////////////////////\r
420  * API functions\r
421  */\r
422 \r
423 size_t b64_encode(void const *src, size_t srcSize, char *dest, size_t destLen)\r
424 {\r
425     /* Use Null Object (Variable) here for rc, so do not need to check\r
426      * elsewhere.\r
427      */\r
428     B64_RC  rc_;\r
429 \r
430     return b64_encode_((unsigned char const*)src, srcSize, dest, destLen, 0, &rc_);\r
431 }\r
432 \r
433 size_t b64_encode2( void const  *src\r
434                 ,   size_t      srcSize\r
435                 ,   char        *dest\r
436                 ,   size_t      destLen\r
437                 ,   unsigned    flags\r
438                 ,   int         lineLen /* = -1 */\r
439                 ,   B64_RC      *rc     /* = NULL */)\r
440 {\r
441     /* Use Null Object (Variable) here for rc, so do not need to check\r
442      * elsewhere\r
443      */\r
444     B64_RC  rc_;\r
445     if(NULL == rc)\r
446     {\r
447         rc = &rc_;\r
448     }\r
449 \r
450     switch(B64_F_LINE_LEN_MASK & flags)\r
451     {\r
452         case    B64_F_LINE_LEN_USE_PARAM:\r
453             if(lineLen >= 0)\r
454             {\r
455                 break;\r
456             }\r
457             /* Fall through to 64 */\r
458         case    B64_F_LINE_LEN_64:\r
459             lineLen = 64;\r
460             break;\r
461         case    B64_F_LINE_LEN_76:\r
462             lineLen = 76;\r
463             break;\r
464         default:\r
465             /*the following assert makes a compiler error with icc*/\r
466             /*assert(!"Bad line length flag specified to b64_encode2()");*/\r
467         case    B64_F_LINE_LEN_INFINITE:\r
468             lineLen = 0;\r
469             break;\r
470     }\r
471 \r
472     assert(0 == (lineLen % 4));\r
473 \r
474     return b64_encode_((unsigned char const*)src, srcSize, dest, destLen, (unsigned)lineLen, rc);\r
475 }\r
476 \r
477 size_t b64_decode(char const *src, size_t srcLen, void *dest, size_t destSize)\r
478 {\r
479     /* Use Null Object (Variable) here for rc and badChar, so do not need to\r
480      * check elsewhere.\r
481      */\r
482     char const  *badChar_;\r
483     B64_RC      rc_;\r
484 \r
485     return b64_decode_(src, srcLen, (unsigned char*)dest, destSize, B64_F_STOP_ON_NOTHING, &badChar_, &rc_);\r
486 }\r
487 \r
488 size_t b64_decode2( char const  *src\r
489                 ,   size_t      srcLen\r
490                 ,   void        *dest\r
491                 ,   size_t      destSize\r
492                 ,   unsigned    flags\r
493                 ,   char const  **badChar   /* = NULL */\r
494                 ,   B64_RC      *rc         /* = NULL */)\r
495 {\r
496     char const      *badChar_;\r
497     B64_RC          rc_;\r
498 \r
499     /* Use Null Object (Variable) here for rc and badChar, so do not need to\r
500      * check elsewhere.\r
501      */\r
502     if(NULL == badChar)\r
503     {\r
504         badChar = &badChar_;\r
505     }\r
506     if(NULL == rc)\r
507     {\r
508         rc = &rc_;\r
509     }\r
510 \r
511     return b64_decode_(src, srcLen, (unsigned char*)dest, destSize, flags, badChar, rc);\r
512 }\r
513 \r
514 /* ////////////////////////////////////////////////////////////////////////// */\r
515 \r
516 #ifdef B64_DOCUMENTATION_SKIP_SECTION\r
517 struct b64ErrorString_t_\r
518 #else /* !B64_DOCUMENTATION_SKIP_SECTION */\r
519 typedef struct b64ErrorString_t_    b64ErrorString_t_;\r
520 struct b64ErrorString_t_\r
521 #endif /* !B64_DOCUMENTATION_SKIP_SECTION */\r
522 {\r
523     int         code;   /*!< The error code. */\r
524     char const  *str;   /*!< The string.        */\r
525     size_t      len;    /*!< The string length. */\r
526 };\r
527 \r
528 \r
529 \r
530 #define SEVERITY_STR_DECL(rc, desc)                                                         \\r
531                                                                                             \\r
532     static const char               s_str##rc[] =   desc;                                   \\r
533     static const b64ErrorString_t_  s_rct##rc = { rc, s_str##rc, NUM_ELEMENTS(s_str##rc) - 1 }\r
534 \r
535 \r
536 #define SEVERITY_STR_ENTRY(rc)                                                          \\r
537                                                                                         \\r
538     &s_rct##rc\r
539 \r
540 \r
541 static char const *b64_LookupCodeA_(int code, b64ErrorString_t_ const **mappings, size_t cMappings, size_t *len)\r
542 {\r
543     /* Use Null Object (Variable) here for len, so do not need to check\r
544      * elsewhere.\r
545      */\r
546     size_t  len_;\r
547 \r
548     if(NULL == len)\r
549     {\r
550         len = &len_;\r
551     }\r
552 \r
553     /* Checked, indexed search. */\r
554     if( code >= 0 &&\r
555         code < B64_max_RC_value)\r
556     {\r
557         if(code == mappings[code]->code)\r
558         {\r
559             return (*len = mappings[code]->len, mappings[code]->str);\r
560         }\r
561     }\r
562 \r
563     /* Linear search. Should only be needed if order in\r
564      * b64_LookupErrorStringA_() messed up.\r
565      */\r
566     { size_t i; for(i = 0; i < cMappings; ++i)\r
567     {\r
568         if(code == mappings[i]->code)\r
569         {\r
570             return (*len = mappings[i]->len, mappings[i]->str);\r
571         }\r
572     }}\r
573 \r
574     return (*len = 0, "");\r
575 }\r
576 \r
577 static char const *b64_LookupErrorStringA_(int error, size_t *len)\r
578 {\r
579     SEVERITY_STR_DECL(B64_RC_OK                     ,   "Operation was successful"                                              );\r
580     SEVERITY_STR_DECL(B64_RC_INSUFFICIENT_BUFFER    ,   "The given translation buffer was not of sufficient size"               );\r
581     SEVERITY_STR_DECL(B64_RC_TRUNCATED_INPUT        ,   "The input did not represent a fully formed stream of octet couplings"  );\r
582     SEVERITY_STR_DECL(B64_RC_DATA_ERROR             ,   "Invalid data"                                                          );\r
583 \r
584     static const b64ErrorString_t_    *s_strings[] = \r
585     {\r
586         SEVERITY_STR_ENTRY(B64_RC_OK),\r
587         SEVERITY_STR_ENTRY(B64_RC_INSUFFICIENT_BUFFER),\r
588         SEVERITY_STR_ENTRY(B64_RC_TRUNCATED_INPUT),\r
589         SEVERITY_STR_ENTRY(B64_RC_DATA_ERROR),\r
590     };\r
591 \r
592     return b64_LookupCodeA_(error, s_strings, NUM_ELEMENTS(s_strings), len);\r
593 }\r
594 \r
595 char const *b64_getErrorString(B64_RC code)\r
596 {\r
597     return b64_LookupErrorStringA_((int)code, NULL);\r
598 }\r
599 \r
600 size_t b64_getErrorStringLength(B64_RC code)\r
601 {\r
602     size_t  len;\r
603 \r
604     return (b64_LookupErrorStringA_((int)code, &len), len);\r
605 }\r
606 \r
607 /* ////////////////////////////////////////////////////////////////////////// */\r