1 /* Creation date: 2008-04-06T02:35:32Z
2  * Authors: Don
3  */
4 
5 /*
6 
7  Copyright (c) 2007-2010 Don Owens <don@regexguy.com>.  All rights reserved.
8 
9  This is free software; you can redistribute it and/or modify it under
10  the Perl Artistic license.  You should have received a copy of the
11  Artistic license with this distribution, in the file named
12  "Artistic".  You may also obtain a copy from
13  http://regexguy.com/license/Artistic
14 
15  This program is distributed in the hope that it will be useful, but
16  WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 */
20 
21 /* $Header: /repository/projects/libjsonevt/utf32.c,v 1.3 2009-02-23 17:46:55 don Exp $ */
22 
23 #include "utf32.h"
24 
25 #define SAFE_SET_POINTER_VAL(ptr, val) if (ptr) { *(ptr) = val; }
26 
27 uint32_t
utf32_bytes_to_unicode(const uint8_t * orig_buf,uint32_t buf_len,uint32_t * ret_len,uint32_t is_little_endian)28 utf32_bytes_to_unicode(const uint8_t *orig_buf, uint32_t buf_len, uint32_t *ret_len,
29                        uint32_t is_little_endian) {
30 
31     const uint8_t *s = orig_buf;
32 
33     if (buf_len < 4) {
34         /* must be at least 4 bytes in a valid utf-32 sequence*/
35         SAFE_SET_POINTER_VAL(ret_len, 0);
36         return 0;
37     }
38 
39     SAFE_SET_POINTER_VAL(ret_len, 4);
40 
41     if (is_little_endian) {
42         return ( *s | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) );
43     }
44     else {
45         return ( s[3] | (s[2] << 8) | (s[1] << 16) | (*s << 24) );
46     }
47 
48     return 0;
49 }
50 
51 uint32_t
utf32_unicode_to_bytes(uint32_t cp,uint8_t * out_buf,uint32_t output_little_endian)52 utf32_unicode_to_bytes(uint32_t cp, uint8_t *out_buf, uint32_t output_little_endian) {
53     uint8_t *d = out_buf;
54 
55     /* 0xd800 .. 0xdfff are ill-formed */
56     if (cp >= 0xd800 && cp <= 0xdfff) {
57         *d = 0;
58         return 0;
59     }
60 
61     if (output_little_endian) {
62         *d++ = cp  & 0xff;
63         *d++ = (cp & 0xff00)     >> 8;
64         *d++ = (cp & 0xff0000)   >> 16;
65         *d++ = (cp & 0xff000000) >> 24;
66 
67         return 4;
68     }
69     else {
70         *d++ = (cp & 0xff000000) >> 24;
71         *d++ = (cp & 0xff0000)   >> 16;
72         *d++ = (cp & 0xff00)     >> 8;
73         *d++ = cp  & 0xff;
74 
75         return 4;
76     }
77 
78     return 0;
79 }
80 
81 
82