366982ec21aaea921cbd5a8de0a322b18cd4dda1
[platform/upstream/groff.git] / src / libs / libgroff / unicode.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 2002-2014  Free Software Foundation, Inc.
3      Written by Werner Lemberg <wl@gnu.org>
4
5 This file is part of groff.
6
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "lib.h"
21 #include "cset.h"
22 #include "stringclass.h"
23
24 #include "unicode.h"
25
26 const char *check_unicode_name(const char *u)
27 {
28   if (*u != 'u')
29     return 0;
30   const char *p = ++u;
31   for (;;) {
32     int val = 0;
33     const char *start = p;
34     for (;;) {
35       // only uppercase hex digits allowed
36       if (!csxdigit(*p))
37         return 0;
38       if (csdigit(*p))
39         val = val*0x10 + (*p-'0');
40       else if (csupper(*p))
41         val = val*0x10 + (*p-'A'+10);
42       else
43         return 0;
44       // biggest Unicode value is U+10FFFF
45       if (val > 0x10FFFF)
46         return 0;
47       p++;
48       if (*p == '\0' || *p == '_')
49         break;
50     }
51     // surrogates not allowed
52     if ((val >= 0xD800 && val <= 0xDBFF) || (val >= 0xDC00 && val <= 0xDFFF))
53       return 0;
54     if (val > 0xFFFF) {
55       if (*start == '0')        // no leading zeros allowed if > 0xFFFF
56         return 0;
57     }
58     else if (p - start != 4)    // otherwise, check for exactly 4 hex digits
59       return 0;
60     if (*p == '\0')
61       break;
62     p++;
63   }
64   return u;
65 }