annotate lib/unistr/u32-to-u8.c @ 40057:b06060465f09

maint: Run 'make update-copyright'
author Paul Eggert <eggert@cs.ucla.edu>
date Tue, 01 Jan 2019 00:25:11 +0100
parents 10eb9086bea0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1 /* Convert UTF-32 string to UTF-8 string.
40057
b06060465f09 maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents: 19484
diff changeset
2 Copyright (C) 2002, 2006-2007, 2009-2019 Free Software Foundation, Inc.
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3 Written by Bruno Haible <bruno@clisp.org>, 2002.
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
4
9307
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
5 This program is free software: you can redistribute it and/or modify it
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
6 under the terms of the GNU Lesser General Public License as published
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
7 by the Free Software Foundation; either version 3 of the License, or
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
8 (at your option) any later version.
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9307
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
13 Lesser General Public License for more details.
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
14
9307
ad8a75a45dc9 Change copyright notice from LGPLv2.0+ to LGPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8038
diff changeset
15 You should have received a copy of the GNU Lesser General Public License
19190
9759915b2aca all: prefer https: URLs
Paul Eggert <eggert@cs.ucla.edu>
parents: 18626
diff changeset
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18 #include <config.h>
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20 /* Specification. */
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21 #include "unistr.h"
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23 #define FUNC u32_to_u8
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
24 #define SRC_UNIT uint32_t
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
25 #define DST_UNIT uint8_t
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
26
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
27 #include <errno.h>
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
28 #include <stdlib.h>
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
29 #include <string.h>
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
30
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
31 DST_UNIT *
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
32 FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
33 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
34 const SRC_UNIT *s_end = s + n;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
35 /* Output string accumulator. */
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
36 DST_UNIT *result;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
37 size_t allocated;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
38 size_t length;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
39
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
40 if (resultbuf != NULL)
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
41 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
42 result = resultbuf;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
43 allocated = *lengthp;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
44 }
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
45 else
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
46 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
47 result = NULL;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
48 allocated = 0;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
49 }
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
50 length = 0;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
51 /* Invariants:
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
52 result is either == resultbuf or == NULL or malloc-allocated.
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
53 If length > 0, then result != NULL. */
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
54
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
55 while (s < s_end)
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
56 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
57 ucs4_t uc;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
58 int count;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
59
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
60 /* Fetch a Unicode character from the input string. */
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
61 uc = *s++;
8038
476e04edf8c6 Rename u32-mbtouc-safe -> u32-mbtouc, u32_mbtouc_safe -> u32_mbtouc.
Bruno Haible <bruno@clisp.org>
parents: 7943
diff changeset
62 /* No need to call the safe variant u32_mbtouc, because
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
63 u8_uctomb will verify uc anyway. */
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
64
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
65 /* Store it in the output string. */
7943
72ebc68d77bf Various fixes.
Bruno Haible <bruno@clisp.org>
parents: 7811
diff changeset
66 count = u8_uctomb (result + length, uc, allocated - length);
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
67 if (count == -1)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
68 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
69 if (!(result == resultbuf || result == NULL))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
70 free (result);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
71 errno = EILSEQ;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
72 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
73 }
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
74 if (count == -2)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
75 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
76 DST_UNIT *memory;
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
77
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
78 allocated = (allocated > 0 ? 2 * allocated : 12);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
79 if (length + 6 > allocated)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
80 allocated = length + 6;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
81 if (result == resultbuf || result == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
82 memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
83 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
84 memory =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
85 (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
86
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
87 if (memory == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
88 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
89 if (!(result == resultbuf || result == NULL))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
90 free (result);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
91 errno = ENOMEM;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
92 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
93 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
94 if (result == resultbuf && length > 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
95 memcpy ((char *) memory, (char *) result,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
96 length * sizeof (DST_UNIT));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
97 result = memory;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
98 count = u8_uctomb (result + length, uc, allocated - length);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
99 if (count < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
100 abort ();
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
101 }
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
102 length += count;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
103 }
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
104
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
105 if (length == 0)
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
106 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
107 if (result == NULL)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
108 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
109 /* Return a non-NULL value. NULL means error. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
110 result = (DST_UNIT *) malloc (1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
111 if (result == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
112 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
113 errno = ENOMEM;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
114 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
115 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
116 }
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
117 }
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
118 else if (result != resultbuf && length < allocated)
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
119 {
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
120 /* Shrink the allocated memory if possible. */
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
121 DST_UNIT *memory;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
122
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
123 memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
124 if (memory != NULL)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9307
diff changeset
125 result = memory;
7811
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
126 }
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
127
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
128 *lengthp = length;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
129 return result;
df8a5b8809d4 New module 'unistr/u32-to-u8'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
130 }