1 /*
2 Copyright (C) 2011-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: dk3enc.ctr
12 */
13 
14 /**	@file dk3enc.c The dk3enc module.
15 */
16 
17 
18 #include <libdk3c/dk3all.h>
19 
20 
21 
22 
23 
24 
25 
26 /**	Binary to text encoding names.
27 	Order here must match order of DK3_DATA_ENCODING_xxx in dk3const.h.
28 */
29 static dkChar const * const dk3enc_data_encoding_names[] = {
30 /*  0 */ dkT("HEX"),
31 /*  1 */ dkT("ASCII-85"),
32 /*  2 */ dkT("R-ASCII-85"),
33 /*  3 */ dkT("H"),
34 /*  4 */ dkT("A"),
35 /*  5 */ dkT("R"),
36 /*  6 */ dkT("A85"),
37 /*  7 */ dkT("RA85"),
38 NULL
39 };
40 
41 
42 
43 /**	Encoding names for file contents encodings.
44 */
45 static dkChar const * const dk3enc_text_encoding_names[] = {
46 /*  0 */ dkT("PLAIN"),
47 /*  1 */ dkT("UTF-8"),
48 /*  2 */ dkT("UTF-16"),
49 /*  3 */ dkT("UTF-16.MSB"),
50 /*  4 */ dkT("UTF-16.LSB"),
51 /*  5 */ dkT("UC32"),
52 /*  6 */ dkT("UC32.MSB"),
53 /*  7 */ dkT("UC32.LSB"),
54 /*  8 */ dkT("ASCII"),
55 /*  9 */ dkT("ISO-LATIN-1"),
56 /* 10 */ dkT("UTF8"),
57 /* 11 */ dkT("UTF16"),
58 /* 12 */ dkT("UTF-16-LE"),
59 /* 13 */ dkT("UTF-16LE"),
60 /* 14 */ dkT("UTF16LE"),
61 /* 15 */ dkT("UTF-16-LSB"),
62 /* 16 */ dkT("UTF-16LSB"),
63 /* 17 */ dkT("UTF16LSB"),
64 /* 18 */ dkT("UTF-16-BE"),
65 /* 19 */ dkT("UTF-16BE"),
66 /* 20 */ dkT("UTF16BE"),
67 /* 21 */ dkT("UTF-16-MSB"),
68 /* 22 */ dkT("UTF-16MSB"),
69 /* 23 */ dkT("UTF16MSB"),
70 /* 24 */ dkT("C32"),
71 /* 25 */ dkT("C32-LE"),
72 /* 26 */ dkT("C32LE"),
73 /* 27 */ dkT("C32-LSB"),
74 /* 28 */ dkT("C32LSB"),
75 /* 29 */ dkT("C32-BE"),
76 /* 30 */ dkT("C32BE"),
77 /* 31 */ dkT("C32-MSB"),
78 /* 32 */ dkT("C32MSB"),
79 NULL
80 };
81 
82 
83 
84 /**	Encoding names for UTF-8 encoding.
85 */
86 static char const * const	dk3enc_utf8_names[] = {
87 /* 0 */
88 "utf-8",
89 
90 /* 1 */
91 "utf8",
92 
93 NULL
94 
95 };
96 
97 
98 /**	Digits used to show hexadecimal characters.
99 */
100 static char const dk3enc_hex_digits[] = {
101 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\0'
102 };
103 
104 
105 /**	Bit mask to obtain last byte of a double word.
106 */
107 static unsigned long const dk3enc_last_byte = 0x000000FFUL;
108 
109 
110 
111 /**	Factors for ASCII85 and reverse ASCII85 encoding.
112 */
113 static unsigned long const dk3enc_f2[] = {
114   1UL,
115   85UL,
116   (85UL * 85UL),
117   (85UL * 85UL * 85UL),
118   (85UL * 85UL * 85UL * 85UL)
119 };
120 
121 
122 
123 /**	Swap byte order for unsigned long.
124 	@param	ul	Original value.
125 	@return	Value in swapped byte order.
126 */
127 static
128 unsigned long
dk3enc_swap_ul(unsigned long ul)129 dk3enc_swap_ul(unsigned long ul)
130 {
131   unsigned long back = 0UL;
132   back =  ((ul >> 24) & 0x000000FFUL);
133   back |= ((ul >>  8) & 0x0000FF00UL);
134   back |= ((ul <<  8) & 0x00FF0000UL);
135   back |= ((ul << 24) & 0xFF000000UL);
136   return back;
137 }
138 
139 
140 
141 /**	Swap byte order for unsigned short.
142 	@param	us	Original value.
143 	@return	Value in swapped byte order.
144 */
145 static
146 unsigned short
dk3enc_swap_us(unsigned short us)147 dk3enc_swap_us(unsigned short us)
148 {
149   unsigned short back = 0U;
150   back = (unsigned short)((us >> 8) & 0x00FFU);
151   back = (unsigned short)(back | (((unsigned)us << 8) & 0xFF00U));
152   return back;
153 }
154 
155 
156 unsigned long
dk3enc_ntohl(unsigned long x)157 dk3enc_ntohl(unsigned long x)
158 {
159   unsigned long back;
160 #if DK3_WORDS_BIGENDIAN
161   back = x;
162 #else
163   back = dk3enc_swap_ul(x);
164 #endif
165   return back;
166 }
167 
168 
169 unsigned long
dk3enc_htonl(unsigned long x)170 dk3enc_htonl(unsigned long x)
171 {
172   unsigned long back;
173 #if DK3_WORDS_BIGENDIAN
174   back = x;
175 #else
176   back = dk3enc_swap_ul(x);
177 #endif
178   return back;
179 }
180 
181 
182 
183 unsigned short
dk3enc_ntohs(unsigned short x)184 dk3enc_ntohs(unsigned short x)
185 {
186   unsigned short back;
187 #if DK3_WORDS_BIGENDIAN
188   back = x;
189 #else
190   back = dk3enc_swap_us(x);
191 #endif
192   return back;
193 }
194 
195 
196 
197 unsigned short
dk3enc_htons(unsigned short x)198 dk3enc_htons(unsigned short x)
199 {
200   unsigned short back;
201 #if DK3_WORDS_BIGENDIAN
202   back = x;
203 #else
204   back = dk3enc_swap_us(x);
205 #endif
206   return back;
207 }
208 
209 
210 
211 unsigned long
dk3enc_uc_to_ul(unsigned long c)212 dk3enc_uc_to_ul(unsigned long c)
213 {
214   c &= 0xFFFFFFFFUL;
215   return c;
216 }
217 
218 
219 
220 unsigned long
dk3enc_dk_to_ul(unsigned long c)221 dk3enc_dk_to_ul(unsigned long c)
222 {
223 #if DK3_CHAR_SIZE > 1
224 #if DK3_CHAR_SIZE > 2
225   c &= 0xFFFFFFFFUL;
226 #else
227   c &= 0x0000FFFFUL;
228 #endif
229 #else
230   c &= 0x000000FFUL;
231 #endif
232   return c;
233 }
234 
235 
236 /**	Convert 32-bit character to UTF-8 following RFC2279.
237 	@param	c	32-bit character to convert.
238 	@param	u8p	Destination buffer.
239 	@param	u8l	Length of @a u8p (number of bytes).
240 	@return	Number of bytes written to @a u8p.
241 */
242 static
243 size_t
dk3enc_uc2utf8_rfc2279(dk3_c32_t c,unsigned char * u8p,size_t u8l)244 dk3enc_uc2utf8_rfc2279(dk3_c32_t c, unsigned char *u8p, size_t u8l)
245 {
246   size_t back = 0;
247   dk3_c32_t x = 0UL;	/* Variable for temporary results. */
248 
249   if(u8p) {
250   if(u8l > 0) {
251     if(c > (dk3_c32_t)0x7FUL) {
252       if(c > (dk3_c32_t)0x000007FFUL) {
253 	if(c > (dk3_c32_t)0x0000FFFFUL) {
254 	  if(c > (dk3_c32_t)0x001FFFFFUL) {
255 	    if(c > (dk3_c32_t)0x03FFFFFFUL) {
256 	      if(c < (dk3_c32_t)0x80000000UL) {		/* 6 Byte */
257 		if(u8l >= 6) {
258 		  back = 6;
259 		  x = c >> 30;
260 		  x &= 0x00000001UL;
261 		  x |= 0x000000FCUL;
262 		  u8p[0] = (unsigned char)x;
263 		  x = c >> 24; x &= 0x0000003FUL; x |= 0x00000080UL;
264 		  u8p[1] = (unsigned char)x;
265 		  x = c >> 18; x &= 0x0000003FUL; x |= 0x00000080UL;
266 		  u8p[2] = (unsigned char)x;
267 		  x = c >> 12; x &= 0x0000003FUL; x |= 0x00000080UL;
268 		  u8p[3] = (unsigned char)x;
269 		  x = c >>  6; x &= 0x0000003FUL; x |= 0x00000080UL;
270 		  u8p[4] = (unsigned char)x;
271 		  x = c & 0x0000003FUL; x |= 0x00000080UL;
272 		  u8p[5] = (unsigned char)x;
273 		}
274 	      }
275 	    } else {				/* 5 Byte */
276 	      if(u8l >= 5) {
277 		back = 5;
278 		x = c >> 24;
279 		x &= 0x00000003UL;
280 		x |= 0x000000F8UL;
281 		u8p[0] = (unsigned char)x;
282 		x = c >> 18; x &= 0x0000003FUL; x |= 0x00000080UL;
283 		u8p[1] = (unsigned char)x;
284 		x = c >> 12; x &= 0x0000003FUL; x |= 0x00000080UL;
285 		u8p[2] = (unsigned char)x;
286 		x = c >>  6; x &= 0x0000003FUL; x |= 0x00000080UL;
287 		u8p[3] = (unsigned char)x;
288 		x = c & 0x0000003FUL; x |= 0x00000080UL;
289 		u8p[4] = (unsigned char)x;
290 	      }
291 	    }
292 	  } else {				/* 4 Byte */
293 	    if(u8l >= 4) {
294 	      back = 4;
295 	      x = c >> 18;
296 	      x &= 0x00000007UL;
297 	      x |= 0x000000F0UL;
298 	      u8p[0] = (unsigned char)x;
299 	      x = c >> 12;
300 	      x &= 0x0000003FUL;
301 	      x |= 0x00000080UL;
302 	      u8p[1] = (unsigned char)x;
303 	      x = c >>  6;
304 	      x &= 0x0000003FUL;
305 	      x |= 0x00000080UL;
306 	      u8p[2] = (unsigned char)x;
307 	      x = c & 0x0000003FUL;
308 	      x |= 0x00000080UL;
309 	      u8p[3] = (unsigned char)x;
310 	    }
311 	  }
312 	} else {				/* 3 Byte */
313 	  if(u8l >= 3) {
314 	    back = 3;
315 	    x = c >> 12;
316 	    x &= 0x0000000FUL;
317 	    x |= 0x000000E0UL;
318 	    u8p[0] = (unsigned char)x;
319 	    x = c >>  6;
320 	    x &= 0x0000003FUL;
321 	    x |= 0x00000080UL;
322 	    u8p[1] = (unsigned char)x;
323 	    x = c & 0x0000003FUL;
324 	    x |= 0x00000080UL;
325 	    u8p[2] = (unsigned char)x;
326 	  }
327 	}
328       } else {					/* 2 Byte */
329 	if(u8l >= 2) {
330 	  back = 2;
331 	  x = c >> 6;
332 	  x &= 0x0000001FUL;
333 	  x |= 0x000000C0UL;
334 	  u8p[0] = (unsigned char)x;
335 	  x = c & 0x0000003FUL;
336 	  x |= 0x00000080UL;
337 	  u8p[1] = (unsigned char)x;
338 	}
339       }
340     } else {					/* 1 Byte */
341       if(u8l >= 1) {
342 	back = 1;
343 	u8p[0] = (unsigned char)(c & 0x0000007FUL);
344       }
345     }
346   }
347   }
348   return back;
349 }
350 
351 
352 
353 /**	Get one 32-bit character from UTF-8 encoded string or buffer.
354 	@param	ucp	Pointer to destination variable.
355 	@param	u8p	Buffer containing UTF-8 encoded data.
356 	@param	u8l	Length of @a u8p (number of bytes).
357 	@param	u8u	Pointer to variable for used bytes from @a u8p.
358 	@return	1 on success, 0 on error.
359 */
360 static
361 int
dk3enc_utf82uc_rfc2279(dk3_c32_t * ucp,unsigned char const * u8p,size_t u8l,size_t * u8u)362 dk3enc_utf82uc_rfc2279(
363   dk3_c32_t *ucp, unsigned char const *u8p,size_t u8l,size_t *u8u
364 )
365 {
366   int		back = 0;
367   unsigned char	u1 = 0x00;		/* Character to process. */
368   dk3_c32_t	res = 0UL;		/* Result. */
369   dk3_c32_t	x1 = 0UL;		/* Result component from 1st byte. */
370   dk3_c32_t	x2 = 0UL;		/* Result component from 2nd byte. */
371   dk3_c32_t	x3 = 0UL;		/* Result component from 3rd byte. */
372   dk3_c32_t	x4 = 0UL;		/* Result component from 4th byte. */
373   dk3_c32_t	x5 = 0UL;		/* Result component from 5th byte. */
374   dk3_c32_t	x6 = 0UL;		/* Result component from 6th byte. */
375   size_t	needed_length = 0;	/* Number of btes needed. */
376 
377   needed_length = 0;
378   if(ucp) {
379   if(u8p) {
380   if(u8l) {
381   if(u8u) {
382   if((u8l) > 0) {
383     u1 = *u8p; needed_length = 1;
384     if(u1 > 0x7F) {					/* > 1 Byte */
385       if((u1 & 0xE0) == 0xC0) {				/* 2 Byte */
386 	needed_length = 2;
387 	if(u8l >= needed_length) {
388 	if((u8p[1] & 0xC0) == 0x80) {
389 	  x1 = u1;
390 	  x1 = x1 << 6;
391 	  x1 = x1 & 0x000007C0UL;
392 	  x2 = u8p[1];
393 	  x2 = x2 & 0x0000003FUL;
394 	  res = (x1 | x2); back = 1;
395 	}
396 	}
397       } else {
398 	if((u1 & 0xF0) == 0xE0) {			/* 3 Byte */
399 	  needed_length = 3;
400 	  if(u8l >= needed_length) {
401 	    if((u8p[1] & 0xC0) == 0x80) {
402 	    if((u8p[2] & 0xC0) == 0x80) {
403 	      x1 = u1;
404 	      x1 = x1 << 12;
405 	      x1 = x1 & 0x0000F000UL;
406 	      x2 = u8p[1];
407 	      x2 = x2 << 6;
408 	      x2 = x2 & 0x00000FC0UL;
409 	      x3 = u8p[2];
410 	      x3 = x3 & 0x0000003FUL;
411 	      res = (x1 | x2 | x3); back = 1;
412 	    }
413 	    }
414 	  }
415 	} else {
416 	  if((u1 & 0xF8) == 0xF0) {			/* 4 Byte */
417 	    needed_length = 4;
418 	    if(u8l >= needed_length) {
419 	      if((u8p[1] & 0xC0) == 0x80) {
420 	      if((u8p[2] & 0xC0) == 0x80) {
421 	      if((u8p[3] & 0xC0) == 0x80) {
422 		x1 = u1;
423 		x2 = u8p[1];
424 		x3 = u8p[2];
425 		x4 = u8p[3];
426 		x1 = x1 << 18;
427 		x1 = x1 & 0x001C0000UL;
428 		x2 = x2 << 12;
429 		x2 = x2 & 0x0003F000UL;
430 		x3 = x3 << 6;
431 		x3 = x3 & 0x00000FC0UL;
432 		x4 = x4 & 0x0000003FUL;
433 		res = (x1 | x2 | x3 | x4); back = 1;
434 	      }
435 	      }
436 	      }
437 	    }
438 	  } else {
439 	    if((u1 & 0xFC) == 0xF8) {			/* 5 Byte */
440 	      needed_length = 5;
441 	      if(u8l >= needed_length) {
442 		if((u8p[1] & 0xC0) == 0x80) {
443 		if((u8p[2] & 0xC0) == 0x80) {
444 		if((u8p[3] & 0xC0) == 0x80) {
445 		if((u8p[4] & 0xC0) == 0x80) {
446 		  x1 = u1;
447 		  x2 = u8p[1];
448 		  x3 = u8p[2];
449 		  x4 = u8p[3];
450 		  x5 = u8p[4];
451 		  x1 = x1 << 24;
452 		  x1 = x1 & 0x03000000UL;
453 		  x2 = x2 << 18;
454 		  x2 = x2 & 0x00FC0000UL;
455 		  x3 = x3 << 12;
456 		  x3 = x3 & 0x0003F000UL;
457 		  x4 = x4 <<  6;
458 		  x4 = x4 & 0x00000FC0UL;
459 		  x5 = x5 & 0x0000003FUL;
460 		  res = (x1 | x2 | x3 | x4 | x5); back = 1;
461 		}
462 		}
463 		}
464 		}
465 	      }
466 	    } else {
467 	      if((u1 & 0xFE) == 0xFC) {			/* 6 Byte */
468 		needed_length = 6;
469 		if(u8l >= needed_length) {
470 		  if((u8p[1] & 0xC0) == 0x80) {
471 		  if((u8p[2] & 0xC0) == 0x80) {
472 		  if((u8p[3] & 0xC0) == 0x80) {
473 		  if((u8p[4] & 0xC0) == 0x80) {
474 		  if((u8p[5] & 0xC0) == 0x80) {
475 		    x1 = 0x40000000UL;
476 		    x2 = u8p[1]; x3 = u8p[2]; x4 = u8p[3];
477 		    x5 = u8p[4]; x6 = u8p[5];
478 		    x2 = x2 << 24;
479 		    x3 = x3 << 18;
480 		    x4 = x4 << 12;
481 		    x5 = x5 <<  6;
482 		    x2 = x2 & 0x3F000000UL;
483 		    x3 = x3 & 0x00FC0000UL;
484 		    x4 = x4 & 0x0003F000UL;
485 		    x5 = x5 & 0x00000FC0UL;
486 		    x6 = x6 & 0x0000003FUL;
487 		    res = (x1 | x2 | x3 | x4 | x5 | x6);
488 		    back = 1;
489 		  }
490 		  }
491 		  }
492 		  }
493 		  }
494 		}
495 	      }
496 	    }
497 	  }
498 	}
499       }
500     } else {						/* 1 Byte */
501       res = u1;
502       back = 1;
503     }
504   }
505   }
506   }
507   }
508   }
509   if(back) {
510     *u8u = needed_length;
511     *ucp = res;
512   }
513   return back;
514 }
515 
516 
517 
518 #if DK3_HAVE_RFC_2279
519 
520 /*
521 	RFC 2279 allowed UTF-8 encoding for 32-bit characters in the
522 	range 0 ... 0x7FFFFFFF.
523 */
524 
525 size_t
dk3enc_uc2utf8(dk3_c32_t c,unsigned char * u8p,size_t u8l)526 dk3enc_uc2utf8(dk3_c32_t c, unsigned char *u8p, size_t u8l)
527 {
528   size_t back;
529 
530   back = dk3enc_uc2utf8_rfc2279(c, u8p, u8l);
531 
532   return back;
533 }
534 
535 int
dk3enc_utf82uc(dk3_c32_t * ucp,unsigned char const * u8p,size_t u8l,size_t * u8u)536 dk3enc_utf82uc(dk3_c32_t *ucp, unsigned char const *u8p,size_t u8l,size_t *u8u)
537 {
538   int back;
539   back = dk3enc_utf82uc_rfc2279(ucp, u8p, u8l, u8u);
540   return back;
541 }
542 
543 
544 #else
545 
546 /*
547 	RFC 3629 replaces (obsoletes) RFC 2279.
548 	32-bit characters are now allowed in the range
549 	0 ... 0x0010FFFF only.
550 */
551 
552 size_t
dk3enc_uc2utf8(dk3_c32_t c,unsigned char * u8p,size_t u8l)553 dk3enc_uc2utf8(dk3_c32_t c, unsigned char *u8p, size_t u8l)
554 {
555   size_t	back = 0;
556 
557   if(c <= (dk3_c32_t)0x0010FFFFUL) {
558     back = dk3enc_uc2utf8_rfc2279(c, u8p, u8l);
559   }
560   return back;
561 }
562 
563 int
dk3enc_utf82uc(dk3_c32_t * ucp,unsigned char const * u8p,size_t u8l,size_t * u8u)564 dk3enc_utf82uc(dk3_c32_t *ucp, unsigned char const *u8p,size_t u8l,size_t *u8u)
565 {
566   int		back	= 0;
567   back = dk3enc_utf82uc_rfc2279(ucp, u8p, u8l, u8u);
568   if(back) {
569     if((*ucp) > (dk3_c32_t)0x0010FFFFUL) {
570       back = 0;
571     }
572   }
573   return back;
574 }
575 
576 #endif
577 
578 
579 
580 size_t
dk3enc_uc2utf16(dk3_c32_t c,dk3_c16_t * u16p,size_t u16l)581 dk3enc_uc2utf16(dk3_c32_t c, dk3_c16_t *u16p, size_t u16l)
582 {
583   size_t	back = 0;
584   dk3_c32_t	ul = 0UL;	/* Low surrogate. */
585   dk3_c32_t	um = 0UL;	/* Hight surrogate. */
586   if((u16p) && (u16l)) {
587     if(c >= (dk3_c32_t)0x00010000UL) {
588       if(c <= (dk3_c32_t)0x0010FFFFUL) {
589         if(u16l >= 2) {
590 	  ul = (dk3_c32_t)((unsigned long)c - 0x00010000UL);
591 	  um = ((ul >> 10) & 0x000003FFUL);
592 	  um |= 0x0000D800UL;
593 	  u16p[0] = (dk3_c16_t)um;
594 	  um = (ul & 0x000003FFUL);
595 	  um |= 0x0000DC00UL;
596 	  u16p[1] = (dk3_c16_t)um;
597 	  back = 2;
598 	}
599       }
600     } else {
601 #if VERSION_BEFORE_20141125
602       if((c & 0x0000DC00UL) != 0x0000DC00UL) {
603         if((c & 0x0000DC00UL) != 0x0000D800UL) {
604 	  *u16p = (dk3_c16_t)c; back = 1;
605 	}
606       }
607 #else
608       if ((0x0000D800UL > (0xFFFFFFFFUL & ((unsigned long)c)))
609           || (0x0000DFFFUL < (0xFFFFFFFFUL & ((unsigned long)c)))
610       ) {
611         *u16p = (dk3_c16_t)c; back = 1;
612       }
613 #endif
614     }
615   }
616   return back;
617 }
618 
619 
620 
621 int
dk3enc_utf162uc(dk3_c32_t * ucp,dk3_c16_t const * u16p,size_t u16l,size_t * u16u)622 dk3enc_utf162uc(dk3_c32_t *ucp, dk3_c16_t const *u16p, size_t u16l, size_t *u16u)
623 {
624   int back = 0;
625   dk3_c32_t		result = 0UL;	/* Result 32-bit character. */
626   dk3_c32_t		ul1 = 0UL;	/* First UC16 used. */
627   dk3_c32_t		ul2 = 0UL;	/* Second UC16 used (if any). */
628 
629   if((ucp) && (u16p) && (u16l) && (u16u)) {
630     *u16u = 0;
631     ul1 = (((dk3_c32_t)(u16p[0])) & 0x0000FFFFUL);
632     ul2 = 0UL;
633     if(u16l > 1) {
634       ul2 = (((dk3_c32_t)(u16p[1])) & 0x0000FFFFUL);
635     }
636     if((ul1 & 0x0000DC00UL) == 0x0000DC00UL) {
637       if(u16l > 1) {
638         if((ul2 & 0x0000DC00UL) == 0x0000D800UL) {
639 	  ul2 = ((ul2 << 10) & 0x000FFC00UL);
640 	  ul1 = (ul1 & 0x000003FFUL);
641 	  result = ul1 | ul2;
642 	  result = (dk3_c32_t)((unsigned long)result + 0x00010000UL);
643 	  *ucp = result; *u16u = 2; back = 1;
644 	}
645       }
646     } else {
647       if((ul1 & 0x0000DC00UL) == 0x0000D800UL) {
648         if(u16l > 1) {
649 	  if((ul2 & 0x0000DC00UL) == 0x0000DC00UL) {
650 	    ul1 = ((ul1 << 10) & 0x000FFC00UL);
651 	    ul2 = (ul2 & 0x000003FFUL);
652 	    result = ul1 | ul2;
653 	    result = (dk3_c32_t)((unsigned long)result + 0x00010000UL);
654 	    *ucp = result; *u16u = 2; back = 1;
655 	  }
656 	}
657       } else {
658         ul1 &= 0x0000FFFFUL;
659 	*ucp = ul1; *u16u = 1; back = 1;
660       }
661     }
662   }
663   return back;
664 }
665 
666 
667 
668 /**	Check whether a character is a digit.
669 	@param	c	Character to check.
670 	@return	1 on success, 0 on error.
671 */
672 static int
dk3enc_c8_is_digit(char c)673 dk3enc_c8_is_digit(char c)
674 {
675   int back = 0;
676   switch(c) {
677     case '0': case '1': case '2': case '3': case '4':
678     case '5': case '6': case '7': case '8': case '9':
679     {
680       back = 1;
681     }
682     break;
683   }
684   return back;
685 }
686 
687 
688 
689 /**	Convert digit to corresponding unsigned long.
690 	@param	c	Digit.
691 	@return	Unsigned long for the digit.
692 */
693 static
694 unsigned long
dk3enc_c8_to_ul(char c)695 dk3enc_c8_to_ul(char c)
696 {
697   unsigned long back = 0UL;
698   if(c == '1') back = 1UL;
699   if(c == '2') back = 2UL;
700   if(c == '3') back = 3UL;
701   if(c == '4') back = 4UL;
702   if(c == '5') back = 5UL;
703   if(c == '6') back = 6UL;
704   if(c == '7') back = 7UL;
705   if(c == '8') back = 8UL;
706   if(c == '9') back = 9UL;
707   return back;
708 }
709 
710 
711 
712 int
dk3enc_ipaddr_to_ul_app(dkChar const * str,unsigned long * ul,dk3_app_t * app)713 dk3enc_ipaddr_to_ul_app(dkChar const *str, unsigned long *ul, dk3_app_t *app)
714 {
715   char		bu[512];
716   int		back = 0;
717 
718   if((str) && (ul)) {
719     if(dk3str_string_to_c8_simple_app(bu, sizeof(bu), str, app)) {
720       back = dk3enc_c8_ipaddr_to_ul_app(bu, ul, app);
721     } else {
722       /* ERROR: Conversion failed! */
723     }
724   }
725   return back;
726 }
727 
728 
729 
730 int
dk3enc_c8_ipaddr_to_ul_app(char const * str,unsigned long * ul,dk3_app_t * app)731 dk3enc_c8_ipaddr_to_ul_app(char const *str, unsigned long *ul, dk3_app_t *app)
732 {
733   int		back = 0;
734   int		state = 0;	/* Current state. */
735   char const	*ptr = NULL;	/* Used to traverse string. */
736   unsigned long	ul1 = 0UL;	/* First part of IP address. */
737   unsigned long	ul2 = 0UL;	/* Second part of IP address. */
738   unsigned long	ul3 = 0UL;	/* Third part of IP address. */
739   unsigned long	ulval = 0UL;	/* Resulting IP address. */
740 
741   if(str && ul) {
742     state = 0; ptr = str; back = 1;
743     ul1 = ul2 = ul3 = ulval = 0UL;
744     while(back && (*ptr)) {
745       if(dk3enc_c8_is_digit(*ptr)) {
746 	switch(state) {
747 	  case 0:
748 	  case 1:
749 	  case 2:
750 	  case 4:
751 	  case 5:
752 	  case 6:
753 	  case 8:
754 	  case 9:
755 	  case 10:
756 	  case 12:
757 	  case 13:
758 	  case 14: {
759 	    ulval = 10UL * ulval + dk3enc_c8_to_ul(*ptr); state++;
760 	  } break;
761 	  default: {
762 	    back = 0;
763 	  } break;
764 	}
765       } else {
766         if(*ptr == '.') {
767 	  switch(state) {
768 	    case 0:
769 	    case 1:
770 	    case 2:
771 	    case 3: {
772 	      ul1 = ulval; ulval = 0UL; state = 4;
773 	    } break;
774 	    case 4:
775 	    case 5:
776 	    case 6:
777 	    case 7: {
778 	      ul2 = ulval; ulval = 0UL; state = 8;
779 	    } break;
780 	    case 8:
781 	    case 9:
782 	    case 10:
783 	    case 11: {
784 	      ul3 = ulval; ulval = 0UL; state = 12;
785 	    } break;
786 	  }
787 	} else {
788 	  back = 0;
789 	}
790       }
791       ptr++;
792     }
793     if((state < 12) || (state > 15)) {
794       back = 0;
795     }
796     if(back) {
797       if(ul1 > 255UL) back = 1;
798       if(ul2 > 255UL) back = 1;
799       if(ul3 > 255UL) back = 1;
800       if(ulval > 255UL) back = 1;
801     }
802     if(back) {
803       ul1 = ul1 << 24;
804       ul1 &= 0xFF000000UL;
805       ul2 = ul2 << 16;
806       ul2 &= 0x00FF0000UL;
807       ul3 = ul3 <<  8;
808       ul3 &= 0x0000FF00UL;
809       ulval &= 0x000000FFUL;
810       ulval = ulval | ul1 | ul2 | ul3;
811       *ul = ulval;
812     } else {
813       if(app) {
814         /* Not an IP address! */
815       }
816     }
817   }
818 
819   return back;
820 }
821 
822 
823 
824 size_t
dk3enc_size_bin_to_a85(size_t s)825 dk3enc_size_bin_to_a85(size_t s)
826 {
827 #if VERSION_BEFORE_20140809
828   size_t	back = 0;
829   int		ec = 0;		/* Error code. */
830   unsigned long ul1 = 0UL;	/* Original size converted to unsigned long. */
831   unsigned long	ul2 = 0UL;	/* Remainder of division by 4. */
832   unsigned long	ul3 = 0UL;	/* Result division by 4. */
833 
834   ul1 = (unsigned long)s;
835   ul2 = ul1 % 4UL;
836   ul3 = ul1 / 4UL;
837   if(ul2) ul2++;			/* for last incomplete block */
838   ul1 = dk3ma_ul_add_ok(
839     dk3ma_ul_mul_ok(ul3, 5UL, &ec),
840     ul2,
841     &ec
842   );					/* add 25 percent */
843   ul1++;				/* final 0x00 byte for string */
844   back = (size_t)ul1;
845   if(ec) back = 0;			/* error checking */
846   if((unsigned long)back != ul1) back = 0;
847 
848   return back;
849 #else
850   size_t	back	= 0;
851   size_t	rem	= 0;	/* Division remainder */
852   size_t	res	= 0;	/* Division result */
853   int		ec	= 0;	/* Error code */
854 
855   rem = s % 4;
856   res = s / 4;
857   if (rem) { rem++; }
858   /* back = 5 * res + rem + 1 */
859   rem++;
860   back = dk3mem_add_size_t(rem,   dk3mem_mul_size_t(5, res, &ec),   &ec);
861   if (ec) { back = 0; }
862 
863   return back;
864 #endif
865 }
866 
867 
868 
869 /**	Convert binary data to ASCII-85 encoded string.
870 	@param	dp	Destination pointer.
871 	@param	sp	Source pointer.
872 	@param	ss	Source size.
873 */
874 static
875 void
dk3enc_do_bin_to_ra85(char * dp,char const * sp,size_t ss)876 dk3enc_do_bin_to_ra85(char *dp, char const *sp, size_t ss)
877 {
878   register char const		*mysp = NULL;	/* Source pointer. */
879   register unsigned char	*mydp = NULL;	/* Destination pointer. */
880   register unsigned long	v = 0UL;	/* Output value. */
881   register size_t		i = 0;		/* Current byte index. */
882   register short		vused = 0;	/* Flag: v is used. */
883 
884   mydp = (unsigned char *)dp; mysp = sp; v = 0UL; vused = 0;
885   for(i = 0; i < ss; i++) {
886     switch(vused++) {
887       case 3: {
888         v |=
889 	((((unsigned long)((unsigned char)(*(mysp++)))) << 24) & 0xFF000000UL);
890       } break;
891       case 2: {
892         v |=
893 	((((unsigned long)((unsigned char)(*(mysp++)))) << 16) & 0x00FF0000UL);
894       } break;
895       case 1: {
896         v |=
897 	((((unsigned long)((unsigned char)(*(mysp++)))) <<  8) & 0x0000FF00UL);
898       } break;
899       default: {
900         v |=
901 	((((unsigned long)((unsigned char)(*(mysp++))))      ) & dk3enc_last_byte);
902       } break;
903     }
904     if(vused >= 4) {
905       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
906       v = v / 85UL;
907       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
908       v = v / 85UL;
909       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
910       v = v / 85UL;
911       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
912       v = v / 85UL;
913       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
914       vused = 0; v = 0UL;
915     }
916   }
917   if(vused) {
918     vused++;
919     while(vused--) {
920       *(mydp++) = (unsigned char)((v % 85UL) + 33UL);
921       v = v / 85UL;
922     }
923   }
924   *mydp = '\0';
925 }
926 
927 
928 
929 int
dk3enc_bin_to_ra85_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)930 dk3enc_bin_to_ra85_app(
931   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
932 )
933 {
934   int		back = 0;
935   size_t	needed_size = 0;	/* Destination buffer minimum size. */
936 
937   if((dp) && (sp) && (ds) && (ss)) {
938     needed_size = dk3enc_size_bin_to_a85(ss);
939     if(needed_size) {
940       if(ds >= needed_size) {
941         dk3enc_do_bin_to_ra85(dp, sp, ss);
942 	back = 1;
943       } else {
944         if(app) {
945 	  /* Destination buffer too small! */
946 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
947 	}
948       }
949     }
950   }
951   return back;
952 }
953 
954 
955 
956 size_t
dk3enc_size_a85_to_bin(size_t s)957 dk3enc_size_a85_to_bin(size_t s)
958 {
959   size_t	back = 0;
960   unsigned long	ul1 = 0UL;	/* Original size converted to unsigned long. */
961   unsigned long	ul2 = 0UL;	/* Remainder of division by 5. */
962   unsigned long	ul3 = 0UL;	/* Result of division by 5. */
963 
964   ul1 = (unsigned long)s;
965   ul2 = ul1 % 5UL;
966   ul3 = ul1 / 5UL;
967   ul1 = 4UL * ul3 + ul2;
968   back = (size_t)ul1;
969 
970   return back;
971 }
972 
973 
974 
975 /**	Check whether a character is from the ASCII-85 charset.
976 	@param	c	Character to check.
977 	@return	1 on success, 0 on error.
978 */
979 static
980 int
dk3enc_c8_is_a85(char c)981 dk3enc_c8_is_a85(char c)
982 {
983   int back = 1;
984   if((int)c < 33) {
985     back = 0;
986   } else {
987     if((int)c > 117) {
988       back = 0;
989     }
990   }
991   return back;
992 }
993 
994 
995 
996 /**	Convert reverse ASCII-85 encoded data to binary data.
997 	@param	dp	Destination pointer.
998 	@param	sp	Source pointer.
999 	@param	ss	Source size.
1000 	@param	app	Application structure for diagnostics, may be NULL.
1001 	@return	Number of binary bytes produced.
1002 */
1003 static
1004 size_t
dk3enc_do_ra85_to_bin(char * dp,char const * sp,size_t ss,dk3_app_t * app)1005 dk3enc_do_ra85_to_bin(char *dp, char const *sp, size_t ss, dk3_app_t *app)
1006 {
1007   size_t	back = 0;
1008   unsigned char	*mydp = NULL;	/* Destination pointer. */
1009   char const	*mysp = NULL;	/* Source pointer. */
1010   unsigned long	v = 0UL;	/* Double-word. */
1011   short		vused = 0;	/* Flag: v is used. */
1012   size_t	i = 0;		/* Index of current source byte. */
1013   int reported_illegal_char = 0;	/* Flag: Error already reported. */
1014 
1015   mydp = (unsigned char *)dp; mysp = sp; v = 0UL; vused = 0;
1016   for(i = 0; i < ss; i++) {
1017     if(dk3enc_c8_is_a85(*mysp)) {
1018       v += dk3enc_f2[vused++] * ((((unsigned long)((unsigned char)(*mysp))) & dk3enc_last_byte) - 33UL);
1019       if(vused >= 5) {
1020         *(mydp++) = (unsigned char)(v         & dk3enc_last_byte);
1021 	*(mydp++) = (unsigned char)((v >>  8) & dk3enc_last_byte);
1022 	*(mydp++) = (unsigned char)((v >> 16) & dk3enc_last_byte);
1023 	*(mydp++) = (unsigned char)((v >> 24) & dk3enc_last_byte);
1024 	back += 4;
1025         v = 0UL; vused = 0;
1026       }
1027     } else {
1028       if(app) {
1029         if(!reported_illegal_char) {
1030 	  reported_illegal_char = 1;
1031 	  /* Illegal character(s) in source string! */
1032 	  dk3app_log_i1(app, DK3_LL_ERROR, 67);
1033 	}
1034       }
1035     }
1036     mysp++;
1037   }
1038   if(vused) {
1039     vused--;
1040     while(vused--) {
1041       *(mydp++) = (unsigned char)(v         & dk3enc_last_byte);
1042       back++;
1043       v = v >> 8;
1044     }
1045   }
1046   return back;
1047 }
1048 
1049 
1050 
1051 size_t
dk3enc_ra85_to_bin_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)1052 dk3enc_ra85_to_bin_app(
1053   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
1054 )
1055 {
1056   size_t back = 0;
1057   size_t needed_size = 0;	/* Minimum output buffer size. */
1058 
1059   if((dp) && (sp) && (ds) && (ss)) {
1060     needed_size = dk3enc_size_a85_to_bin(ss);
1061     if(needed_size) {
1062       if(ds >= needed_size) {
1063         back = dk3enc_do_ra85_to_bin(dp, sp, ss, app);
1064       } else {
1065         if(app) {
1066 	  /* Destination buffer too small! */
1067 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1068 	}
1069       }
1070     }
1071   }
1072   return back;
1073 }
1074 
1075 
1076 
1077 size_t
dk3enc_ra85string_to_bin_app(char * dp,size_t ds,char const * sp,dk3_app_t * app)1078 dk3enc_ra85string_to_bin_app(
1079   char *dp, size_t ds, char const *sp, dk3_app_t *app
1080 )
1081 {
1082   size_t back = 0;
1083 
1084   if(sp) {
1085     back = dk3enc_ra85_to_bin_app(dp, ds, sp, dk3str_c8_len(sp), app);
1086   }
1087   return back;
1088 }
1089 
1090 
1091 
1092 /**	Convert binary data to ASCII-85 string.
1093 	@param	dp	Destination pointer.
1094 	@param	sp	Source pointer.
1095 	@param	ss	Source size.
1096 */
1097 static
1098 void
dk3enc_do_bin_to_a85(char * dp,char const * sp,size_t ss)1099 dk3enc_do_bin_to_a85(char *dp, char const *sp, size_t ss)
1100 {
1101   register unsigned char *mydp = NULL;	/* Destination pointer. */
1102   register unsigned char *mysp = NULL;	/* Source pointer. */
1103   register unsigned long v = 0UL;	/* Double-word. */
1104   register short vused = 0;		/* Flag: v used. */
1105   register short addval = 0;		/* Value to add. */
1106   register size_t i = 0;		/* Index of current source byte. */
1107 
1108   mydp = (unsigned char *)dp;
1109   mysp = (unsigned char *)sp;
1110   v = 0UL;
1111   vused = 0;
1112   for(i = 0; i < ss; i++) {
1113     switch(vused) {
1114       case 3: {
1115         v |= ( ((unsigned long)(*(mysp++)))        & 0x000000FFUL);
1116       } break;
1117       case 2: {
1118         v |= ((((unsigned long)(*(mysp++))) <<  8) & 0x0000FF00UL);
1119       } break;
1120       case 1: {
1121         v |= ((((unsigned long)(*(mysp++))) << 16) & 0x00FF0000UL);
1122       } break;
1123       default: {
1124         v |= ((((unsigned long)(*(mysp++))) << 24) & 0xFF000000UL);
1125       } break;
1126     }
1127     if(++vused >= 4) {
1128       vused = 5;
1129       while(vused--) {
1130         *(mydp++) = (unsigned char)(33UL + v / dk3enc_f2[vused]);
1131 	v = v % dk3enc_f2[vused];
1132       }
1133       v = 0UL; vused = 0;
1134     }
1135   }
1136   if(vused) {
1137     vused++; addval = (short)(5 - vused);
1138     while(vused--) {
1139       *(mydp++) = (unsigned char)(33UL + v / dk3enc_f2[vused + addval]);
1140       v = v % dk3enc_f2[vused + addval];
1141     }
1142   }
1143   *mydp = '\0';
1144 }
1145 
1146 
1147 
1148 int
dk3enc_bin_to_a85_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)1149 dk3enc_bin_to_a85_app(
1150   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
1151 )
1152 {
1153   int back = 0;
1154   size_t needed_size = 0;	/* Minimum output buffer size. */
1155 
1156   if((dp) && (sp) && (ds) && (ss)) {
1157     needed_size = dk3enc_size_bin_to_a85(ss);
1158     if(needed_size) {
1159       if(ds >= needed_size) {
1160         dk3enc_do_bin_to_a85(dp, sp, ss);
1161 	back = 1;
1162       } else {
1163         if(app) {
1164 	  /* Destination buffer too small! */
1165 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1166 	}
1167       }
1168     }
1169   }
1170   return back;
1171 }
1172 
1173 
1174 
1175 /**	Convert ASCII-85 encoded data to binary data.
1176 	@param	dp	Destination pointer.
1177 	@param	sp	Source pointer.
1178 	@param	ss	Source size.
1179 	@param	app	Application structure for diagnostics, may be NULL.
1180 	@return	Number of binary bytes produced.
1181 */
1182 static
1183 size_t
dk3enc_do_a85_to_bin(char * dp,char const * sp,size_t ss,dk3_app_t * app)1184 dk3enc_do_a85_to_bin(char *dp, char const *sp, size_t ss, dk3_app_t *app)
1185 {
1186   register size_t back = 0;
1187   register unsigned char *mydp = NULL;		/* Destination pointer. */
1188   register unsigned char const *mysp = NULL;	/* Source pointer. */
1189   register unsigned long v = 0UL;		/* Double-word. */
1190   register short vused = 0;			/* Flag: v used. */
1191   register size_t i = 0;			/* Current source byte index. */
1192   unsigned long u1 = 0UL;			/* Temporary value. */
1193   unsigned long u2 = 0UL;			/* Temporary value. */
1194   unsigned long u3 = 0UL;			/* Temporary value. */
1195   int reported_illegal_character = 0;
1196 
1197   mydp = (unsigned char *)dp; mysp = (unsigned char *)sp;
1198   v = 0UL; vused = 0;
1199   for(i = 0; i < ss; i++) {
1200     if(*mysp) {
1201       if(dk3enc_c8_is_a85((char)(*mysp))) {
1202         v += dk3enc_f2[4 - vused] *
1203 	((((unsigned long)(*mysp)) & 0x000000FFUL) - 33UL);
1204       } else {
1205         if(!reported_illegal_character) {
1206 	  reported_illegal_character = 1;
1207 	  if(app) {
1208 	    /* Illegal character in source data! */
1209 	    dk3app_log_i1(app, DK3_LL_ERROR, 67);
1210 	  }
1211 	}
1212       }
1213       vused++;
1214       if(vused >= 5) {
1215         *(mydp++) = (unsigned char)((v >> 24) & 0x000000FFUL); back++;
1216 	*(mydp++) = (unsigned char)((v >> 16) & 0x000000FFUL); back++;
1217 	*(mydp++) = (unsigned char)((v >>  8) & 0x000000FFUL); back++;
1218 	*(mydp++) = (unsigned char)( v        & 0x000000FFUL); back++;
1219         v = 0UL; vused = 0;
1220       }
1221     }
1222     mysp++;
1223   }
1224   if(vused) {
1225     u1 = (v >> 24) & 0x000000FFUL;
1226     u2 = (v >> 16) & 0x000000FFUL;
1227     u3 = (v >>  8) & 0x000000FFUL;
1228     switch(vused) {
1229       case 2: {
1230         if(v & 0x00FFFFFFUL) {
1231 	  u1++; if(u1 >= 256UL) u1 = 0UL;
1232 	}
1233 	*(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++;
1234       } break;
1235       case 3: {
1236         if(v & 0x0000FFFFUL) {
1237 	  u2++;
1238 	  if(u2 >= 256UL) {
1239 	    u2 = 0UL;
1240 	    u1++; if(u1 >= 256UL) u1 = 0UL;
1241 	  }
1242 	}
1243 	*(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++;
1244 	*(mydp++) = (unsigned char)(u2 & 0x000000FFUL); back++;
1245       } break;
1246       case 4: {
1247         if(v & 0x000000FFUL) {
1248 	  u3++;
1249 	  if(u3 >= 256UL) {
1250 	    u3 = 0UL;
1251 	    u2++;
1252 	    if(u2 >= 256UL) {
1253 	      u2 = 0UL;
1254 	      u1++; if(u1 >= 256UL) u1 = 0UL;
1255 	    }
1256 	  }
1257 	}
1258 	*(mydp++) = (unsigned char)(u1 & 0x000000FFUL); back++;
1259 	*(mydp++) = (unsigned char)(u2 & 0x000000FFUL); back++;
1260 	*(mydp++) = (unsigned char)(u3 & 0x000000FFUL); back++;
1261       } break;
1262     }
1263   }
1264   return back;
1265 }
1266 
1267 
1268 
1269 size_t
dk3enc_a85_to_bin_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)1270 dk3enc_a85_to_bin_app(
1271   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
1272 )
1273 {
1274   size_t back = 0;
1275   size_t needed_size = 0;	/* Minimum output buffer size. */
1276 
1277   if((dp) && (sp) && (ds) && (ss)) {
1278     needed_size = dk3enc_size_a85_to_bin(ss);
1279     if(needed_size) {
1280       if(ds >= needed_size) {
1281         back = dk3enc_do_a85_to_bin(dp, sp, ss, app);
1282       } else {
1283         if(app) {
1284 	  /* Destination buffer too small! */
1285 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1286 	}
1287       }
1288     }
1289   }
1290   return back;
1291 }
1292 
1293 
1294 
1295 size_t
dk3enc_a85string_to_bin_app(char * dp,size_t ds,char const * sp,dk3_app_t * app)1296 dk3enc_a85string_to_bin_app(char *dp, size_t ds, char const *sp, dk3_app_t *app)
1297 {
1298   size_t back = 0;
1299 
1300   if(sp) {
1301     back = dk3enc_a85_to_bin_app(dp, ds, sp, dk3str_c8_len(sp), app);
1302   }
1303   return back;
1304 }
1305 
1306 
1307 
1308 size_t
dk3enc_size_bin_to_hex(size_t s)1309 dk3enc_size_bin_to_hex(size_t s)
1310 {
1311 #if VERSION_BEFORE_20140809
1312   size_t back = 0;
1313   int ec = 0;			/* Error code. */
1314   unsigned long ul1 = 0UL;	/* Temporary value for calculation. */
1315 
1316   ul1 = (unsigned long)s;
1317   ul1 = dk3ma_ul_mul_ok(ul1, 2UL, &ec);
1318   ul1 = dk3ma_ul_add_ok(ul1, 1UL, &ec);
1319   back = (size_t)ul1;
1320   if(ec) back = 0;
1321   if((unsigned long)back != ul1) back = 0;
1322 
1323   return back;
1324 #else
1325   size_t	back	= 0;
1326   int		ec	= 0;	/* Error code */
1327 
1328   back = dk3mem_add_size_t(1,   dk3mem_mul_size_t(2, s, &ec),   &ec);
1329   if (ec) { back = 0; }
1330 
1331   return back;
1332 #endif
1333 }
1334 
1335 
1336 
1337 size_t
dk3enc_size_hex_to_bin(size_t s)1338 dk3enc_size_hex_to_bin(size_t s)
1339 {
1340   size_t back;
1341 
1342   back = s / 2;
1343   back++;
1344   return back;
1345 }
1346 
1347 
1348 
1349 /**	Get higher half-byte from character.
1350 	@param	c	Source character.
1351 	@return	Higher half-byte of \a c.
1352 */
1353 static
1354 char
dk3enc_c8_high_nibble_hex(char c)1355 dk3enc_c8_high_nibble_hex(char c)
1356 {
1357   char back;
1358   back = dk3enc_hex_digits[ (((unsigned short)c) >> 4) & 0x000FU ];
1359   return back;
1360 }
1361 
1362 
1363 
1364 /**	Get lower half-byte from character.
1365 	@param	c	Source character.
1366 	@return	Lower half-byte of \a c.
1367 */
1368 static
1369 char
dk3enc_c8_low_nibble_hex(char c)1370 dk3enc_c8_low_nibble_hex(char c)
1371 {
1372   char back;
1373   back = dk3enc_hex_digits[  ((unsigned short)c)       & 0x000FU ];
1374   return back;
1375 }
1376 
1377 
1378 
1379 /**	Convert binary data to hexadecimal string.
1380 	@param	dp	Destination pointer.
1381 	@param	sp	Source pointer.
1382 	@param	ss	Source size.
1383 */
1384 static
1385 void
dk3enc_do_bin_to_hex(char * dp,char const * sp,size_t ss)1386 dk3enc_do_bin_to_hex(char *dp, char const *sp, size_t ss)
1387 {
1388   register char *mydp = NULL;		/* Destination pointer. */
1389   register char const *mysp = NULL;	/* Source pointer. */
1390   register size_t i = 0;		/* Current source byte index. */
1391 
1392   mydp = dp; mysp = sp;
1393   for(i = 0; i < ss; i++) {
1394     *(mydp++) = dk3enc_c8_high_nibble_hex(*mysp);
1395     *(mydp++) = dk3enc_c8_low_nibble_hex(*(mysp++));
1396   }
1397   *mydp = '\0';
1398 }
1399 
1400 
1401 
1402 int
dk3enc_bin_to_hex_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)1403 dk3enc_bin_to_hex_app(
1404   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
1405 )
1406 {
1407   int back = 0;
1408   size_t needed_bytes = 0;	/* Minimum output buffer size. */
1409 
1410   if((dp) && (ds) && (sp) && (ss)) {
1411     needed_bytes = dk3enc_size_bin_to_hex(ss);
1412     if(needed_bytes) {
1413       if(ds >= needed_bytes) {
1414         dk3enc_do_bin_to_hex(dp, sp, ss); back = 1;
1415       } else {
1416         if(app) {
1417 	  /* Destination buffer too small1 */
1418 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1419 	}
1420       }
1421     }
1422   }
1423   return back;
1424 }
1425 
1426 
1427 
1428 /**	Convert hexadecimal data to binary data.
1429 	@param	dp	Destination pointer.
1430 	@param	sp	Source pointer.
1431 	@param	ss	Source size.
1432 	@param	app	Application structure for diagnostics, may be NULL.
1433 	@return	Number of bytes created in destination.
1434 */
1435 static
1436 size_t
dk3enc_do_hex_to_bin(char * dp,char const * sp,size_t ss,dk3_app_t * app)1437 dk3enc_do_hex_to_bin(char *dp, char const *sp, size_t ss, dk3_app_t *app)
1438 {
1439   register size_t back = 0;
1440   register char const *mysp = NULL;	/* Source pointer. */
1441   register unsigned char *mydp = NULL;	/* Destination pointer. */
1442   register unsigned char v = 0x00;	/* Current byte to process. */
1443   register short int vused = 0;		/* Flag: v used. */
1444   register size_t i = 0;		/* Current source byte index. */
1445   int reported_illegal_character = 0;	/* Flag: Error already reported. */
1446 
1447   mydp = (unsigned char *)dp;
1448   mysp = sp; v = 0x00; vused = 0U;
1449   for(i = 0; i < ss; i++) {
1450     switch(*mysp) {
1451       case '0':
1452       case '1':
1453       case '2':
1454       case '3':
1455       case '4':
1456       case '5':
1457       case '6':
1458       case '7':
1459       case '8':
1460       case '9':
1461       case 'a':
1462       case 'A':
1463       case 'b':
1464       case 'B':
1465       case 'c':
1466       case 'C':
1467       case 'd':
1468       case 'D':
1469       case 'e':
1470       case 'E':
1471       case 'f':
1472       case 'F':
1473       {
1474         if(vused) {
1475 	  switch(*mysp) {
1476 	    case '0': { v |= 0x00; } break;
1477 	    case '1': { v |= 0x01; } break;
1478 	    case '2': { v |= 0x02; } break;
1479 	    case '3': { v |= 0x03; } break;
1480 	    case '4': { v |= 0x04; } break;
1481 	    case '5': { v |= 0x05; } break;
1482 	    case '6': { v |= 0x06; } break;
1483 	    case '7': { v |= 0x07; } break;
1484 	    case '8': { v |= 0x08; } break;
1485 	    case '9': { v |= 0x09; } break;
1486 	    case 'a': { v |= 0x0A; } break;
1487 	    case 'A': { v |= 0x0A; } break;
1488 	    case 'b': { v |= 0x0B; } break;
1489 	    case 'B': { v |= 0x0B; } break;
1490 	    case 'c': { v |= 0x0C; } break;
1491 	    case 'C': { v |= 0x0C; } break;
1492 	    case 'd': { v |= 0x0D; } break;
1493 	    case 'D': { v |= 0x0D; } break;
1494 	    case 'e': { v |= 0x0E; } break;
1495 	    case 'E': { v |= 0x0E; } break;
1496 	    case 'f': { v |= 0x0F; } break;
1497 	    case 'F': { v |= 0x0F; } break;
1498 	  }
1499 	  *(mydp++) = v; back++; v = 0; vused = 0U;
1500 	} else {
1501 	  switch(*mysp) {
1502 	    case '0': { v = 0x00; } break;
1503 	    case '1': { v = 0x10; } break;
1504 	    case '2': { v = 0x20; } break;
1505 	    case '3': { v = 0x30; } break;
1506 	    case '4': { v = 0x40; } break;
1507 	    case '5': { v = 0x50; } break;
1508 	    case '6': { v = 0x60; } break;
1509 	    case '7': { v = 0x70; } break;
1510 	    case '8': { v = 0x80; } break;
1511 	    case '9': { v = 0x90; } break;
1512 	    case 'a': { v = 0xA0; } break;
1513 	    case 'A': { v = 0xA0; } break;
1514 	    case 'b': { v = 0xB0; } break;
1515 	    case 'B': { v = 0xB0; } break;
1516 	    case 'c': { v = 0xC0; } break;
1517 	    case 'C': { v = 0xC0; } break;
1518 	    case 'd': { v = 0xD0; } break;
1519 	    case 'D': { v = 0xD0; } break;
1520 	    case 'e': { v = 0xE0; } break;
1521 	    case 'E': { v = 0xE0; } break;
1522 	    case 'f': { v = 0xF0; } break;
1523 	    case 'F': { v = 0xF0; } break;
1524 	  }
1525 	  vused = 1U;
1526 	}
1527       } break;
1528       default: {
1529         if(!reported_illegal_character) {
1530 	  reported_illegal_character = 1;
1531 	  if(app) {
1532 	    /* Illegal character(s) in source! */
1533 	    dk3app_log_i1(app, DK3_LL_ERROR, 67);
1534 	  }
1535 	}
1536       } break;
1537     }
1538     mysp++;
1539   }
1540   if(vused) {
1541     *mydp = v; back++;
1542   }
1543   return back;
1544 }
1545 
1546 
1547 
1548 size_t
dk3enc_hex_to_bin_app(char * dp,size_t ds,char const * sp,size_t ss,dk3_app_t * app)1549 dk3enc_hex_to_bin_app(
1550   char *dp, size_t ds, char const *sp, size_t ss, dk3_app_t *app
1551 )
1552 {
1553   size_t back = 0;
1554   size_t needed_bytes = 0;	/* Minimum output buffer size. */
1555 
1556   if((dp) && (ds) && (sp) && (ss)) {
1557     needed_bytes = dk3enc_size_hex_to_bin(ss);
1558     if(needed_bytes) {
1559       if(ds >= needed_bytes) {
1560         back = dk3enc_do_hex_to_bin(dp, sp, ss, app);
1561       } else {
1562         if(app) {
1563 	  /* Destination buffer too small! */
1564 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1565 	}
1566       }
1567     }
1568   }
1569   return back;
1570 }
1571 
1572 
1573 
1574 size_t
dk3enc_hexstring_to_bin_app(char * dp,size_t ds,char const * sp,dk3_app_t * app)1575 dk3enc_hexstring_to_bin_app(
1576   char *dp, size_t ds, char const *sp, dk3_app_t *app
1577 )
1578 {
1579   size_t back = 0;
1580 
1581   if(sp) {
1582     back = dk3enc_hex_to_bin_app(dp, ds, sp, dk3str_c8_len(sp), app);
1583   }
1584   return back;
1585 }
1586 
1587 
1588 
1589 size_t
dk3enc_size_hexstring_to_bin(char const * s)1590 dk3enc_size_hexstring_to_bin(char const *s)
1591 {
1592   size_t back = 0;
1593 
1594   if(s) {
1595     back = dk3str_c8_len(s);
1596     back = dk3enc_size_hex_to_bin(back);
1597   }
1598   return back;
1599 }
1600 
1601 
1602 
1603 size_t
dk3enc_size_a85string_to_bin(char const * s)1604 dk3enc_size_a85string_to_bin(char const *s)
1605 {
1606   size_t back = 0;
1607 
1608   if(s) {
1609     back = dk3str_c8_len(s);
1610     back = dk3enc_size_a85_to_bin(back);
1611   }
1612   return back;
1613 }
1614 
1615 
1616 
1617 int
dk3enc_get_type_app(dkChar const * n,dk3_app_t * app)1618 dk3enc_get_type_app(dkChar const *n, dk3_app_t *app)
1619 {
1620   int back = -1;
1621   if(n) {
1622     back = dk3str_array_index(dk3enc_data_encoding_names, n, 0);
1623     if(back >= 0) {
1624       switch(back) {
1625         case 0: case 3: {
1626 	  back = DK3_DATA_ENCODING_HEX;
1627 	} break;
1628 	case 1: case 4: case 6: {
1629 	  back = DK3_DATA_ENCODING_ASCII85;
1630 	} break;
1631 	case 2: case 5: case 7: {
1632 	  back = DK3_DATA_ENCODING_REVERSE_ASCII85;
1633 	} break;
1634       }
1635     } else {
1636       if(app) {
1637         dk3app_log_i3(app, DK3_LL_ERROR, 129, 130, n);
1638       }
1639     }
1640   }
1641   return back;
1642 }
1643 
1644 
1645 dkChar const *
dk3enc_get_data_encoding_name(int t)1646 dk3enc_get_data_encoding_name(int t)
1647 {
1648   dkChar const *back = NULL;
1649   if((t >= 0) && (t <= 2)) {
1650     back = dk3enc_data_encoding_names[t];
1651   }
1652   return back;
1653 }
1654 
1655 
1656 
1657 int
dk3enc_get_text_encoding_app(dkChar const * en,dk3_app_t * app)1658 dk3enc_get_text_encoding_app(dkChar const *en, dk3_app_t *app)
1659 {
1660   int back = -1;
1661   int i;
1662 
1663   if(app) { back = dk3app_get_output_encoding(app); }
1664   if(en) {
1665     i = dk3str_array_index(dk3enc_text_encoding_names, en, 0);
1666     switch(i) {
1667       case 0: case 8: case 9: {
1668         back = DK3_FILE_ENCODING_ASCII;
1669       } break;
1670       case 1: case 10: {
1671         back = DK3_FILE_ENCODING_UTF8;
1672       } break;
1673       case 2: case 11: {
1674 #if DK3_HAVE_BIGENDIAN
1675 	back = DK3_FILE_ENCODING_UTF16_MSB_FIRST;
1676 #else
1677 	back = DK3_FILE_ENCODING_UTF16_LSB_FIRST;
1678 #endif
1679       } break;
1680       case 3: case 18: case 19: case 20: case 21: case 22: case 23: {
1681         back = DK3_FILE_ENCODING_UTF16_MSB_FIRST;
1682       } break;
1683       case 4: case 12: case 13: case 14: case 15: case 16: case 17: {
1684         back = DK3_FILE_ENCODING_UTF16_LSB_FIRST;
1685       } break;
1686       case 5: case 24: {
1687 #if DK3_HAVE_BIGENDIAN
1688 	back = DK3_FILE_ENCODING_UNICODE_MSB_FIRST;
1689 #else
1690 	back = DK3_FILE_ENCODING_UNICODE_LSB_FIRST;
1691 #endif
1692       } break;
1693       case 6: case 29: case 30: case 31: case 32: {
1694         back = DK3_FILE_ENCODING_UNICODE_MSB_FIRST;
1695       } break;
1696       case 7: case 25: case 26: case 27: case 28: {
1697         back = DK3_FILE_ENCODING_UNICODE_LSB_FIRST;
1698       } break;
1699       default: {
1700         if(app) {
1701 	  /* ERROR: Unknown text encoding name! */
1702 	  dk3app_log_i3(app, DK3_LL_ERROR, 129, 130, en);
1703 	}
1704       } break;
1705     }
1706   }
1707   return back;
1708 }
1709 
1710 
1711 
1712 int
dk3enc_get_encoding(dk3_app_t * app)1713 dk3enc_get_encoding(dk3_app_t *app)
1714 {
1715   int		 back = 0;
1716 #if DK3_CHAR_SIZE == 1
1717   char		*ptr;
1718 #endif
1719   if(app) {
1720     back = dk3app_get_encoding(app);
1721   } else {
1722 #if DK3_CHAR_SIZE > 1
1723 #if DK3_CHAR_SIZE > 2
1724     back = DK3_ENCODING_UNICODE;
1725 #else
1726     back = DK3_ENCODING_UTF16;
1727 #endif
1728 #else
1729     back = DK3_ENCODING_PLAIN;
1730     ptr = getenv("LANG");
1731     if(ptr) {
1732       ptr = dk3str_c8_chr(ptr, '.');
1733       if(ptr) {
1734         ptr++;
1735 	switch(dk3str_c8_array_index(dk3enc_utf8_names, ptr, 0)) {
1736 	  case 0: case 1: {
1737 	    back = DK3_ENCODING_UTF8;
1738 	  } break;
1739 	}
1740       }
1741     }
1742 #endif
1743   }
1744   return back;
1745 }
1746 
1747 
1748 
1749 /* vim: set ai sw=2 : */
1750 
1751