1 /* Store a character in UTF-8 string.
2    Copyright (C) 2002, 2005-2006, 2009-2020 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2002.
4 
5    This program is free software: you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published
7    by the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17 
18 #include <config.h>
19 
20 #if defined IN_LIBUNISTRING
21 /* Tell unistr.h to declare u8_uctomb as 'extern', not 'static inline'.  */
22 # include "unistring-notinline.h"
23 #endif
24 
25 /* Specification.  */
26 #include "unistr.h"
27 
28 #ifndef FALLTHROUGH
29 # if __GNUC__ < 7
30 #  define FALLTHROUGH ((void) 0)
31 # else
32 #  define FALLTHROUGH __attribute__ ((__fallthrough__))
33 # endif
34 #endif
35 
36 #if !HAVE_INLINE
37 
38 int
u8_uctomb(uint8_t * s,ucs4_t uc,int n)39 u8_uctomb (uint8_t *s, ucs4_t uc, int n)
40 {
41   if (uc < 0x80)
42     {
43       if (n > 0)
44         {
45           s[0] = uc;
46           return 1;
47         }
48       /* else return -2, below.  */
49     }
50   else
51     {
52       int count;
53 
54       if (uc < 0x800)
55         count = 2;
56       else if (uc < 0x10000)
57         {
58           if (uc < 0xd800 || uc >= 0xe000)
59             count = 3;
60           else
61             return -1;
62         }
63       else if (uc < 0x110000)
64         count = 4;
65       else
66         return -1;
67 
68       if (n >= count)
69         {
70           switch (count) /* note: code falls through cases! */
71             {
72             case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000;
73               FALLTHROUGH;
74             case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800;
75               FALLTHROUGH;
76             case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0;
77           /*case 1:*/ s[0] = uc;
78             }
79           return count;
80         }
81     }
82   return -2;
83 }
84 
85 #endif
86