blob: 4f84d4ad5cd2fd52847ebd9ace20a776103a7502 [file] [log] [blame]
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +04301/*
2 * Copyright © 2019 Ebrahim Byagowi
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 */
25
26#include "hb.hh"
27#include "hb-machinery.hh"
Ebrahim Byagowi47d82712019-09-06 20:33:10 +043028#include "hb-number-parser.hh"
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043029
30#include <locale.h>
31#ifdef HAVE_XLOCALE_H
32#include <xlocale.h>
33#endif
34
Ebrahim Byagowie2cecf12019-09-03 15:14:21 +043035template<typename T, typename Func>
Ebrahim Byagowib5e68052019-09-03 15:23:40 +043036static bool
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043037_parse_number (const char **pp, const char *end, T *pv,
38 bool whole_buffer, Func f)
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043039{
40 char buf[32];
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043041 unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1,
42 (unsigned int) (end - *pp));
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043043 strncpy (buf, *pp, len);
44 buf[len] = '\0';
45
46 char *p = buf;
47 char *pend = p;
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043048
49 errno = 0;
Ebrahim Byagowib5e68052019-09-03 15:23:40 +043050 *pv = f (p, &pend);
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043051 if (unlikely (errno || p == pend ||
52 /* Check if consumed whole buffer if is requested */
53 (whole_buffer && pend - p != end - *pp))) return false;
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043054
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043055 *pp += pend - p;
56 return true;
57}
58
Ebrahim Byagowia77bb7e2019-09-03 14:49:14 +043059bool
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043060hb_parse_int (const char **pp, const char *end, int *pv, bool whole_buffer)
Ebrahim Byagowie2cecf12019-09-03 15:14:21 +043061{
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043062 return _parse_number<int> (pp, end, pv, whole_buffer,
63 [] (const char *p, char **end)
64 { return strtol (p, end, 10); });
Ebrahim Byagowie2cecf12019-09-03 15:14:21 +043065}
66
67bool
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043068hb_parse_uint (const char **pp, const char *end, unsigned int *pv,
69 bool whole_buffer, int base)
Ebrahim Byagowia77bb7e2019-09-03 14:49:14 +043070{
Ebrahim Byagowi65690b52019-09-03 23:09:47 +043071 return _parse_number<unsigned int> (pp, end, pv, whole_buffer,
72 [base] (const char *p, char **end)
73 { return strtoul (p, end, base); });
Ebrahim Byagowia77bb7e2019-09-03 14:49:14 +043074}
75
76
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +043077#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
78#define USE_XLOCALE 1
79#define HB_LOCALE_T locale_t
80#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr)
81#define HB_FREE_LOCALE(loc) freelocale (loc)
82#elif defined(_MSC_VER)
83#define USE_XLOCALE 1
84#define HB_LOCALE_T _locale_t
85#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName)
86#define HB_FREE_LOCALE(loc) _free_locale (loc)
87#define strtod_l(a, b, c) _strtod_l ((a), (b), (c))
88#endif
89
90#ifdef USE_XLOCALE
91
92#if HB_USE_ATEXIT
93static void free_static_C_locale ();
94#endif
95
96static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>,
97 hb_C_locale_lazy_loader_t>
98{
99 static HB_LOCALE_T create ()
100 {
101 HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
102
103#if HB_USE_ATEXIT
104 atexit (free_static_C_locale);
105#endif
106
107 return C_locale;
108 }
109 static void destroy (HB_LOCALE_T p)
110 {
111 HB_FREE_LOCALE (p);
112 }
113 static HB_LOCALE_T get_null ()
114 {
115 return nullptr;
116 }
117} static_C_locale;
118
119#if HB_USE_ATEXIT
120static
121void free_static_C_locale ()
122{
123 static_C_locale.free_instance ();
124}
125#endif
126
127static HB_LOCALE_T
128get_C_locale ()
129{
130 return static_C_locale.get_unconst ();
131}
132#endif /* USE_XLOCALE */
133
134bool
Ebrahim Byagowi57f88e12019-09-04 01:20:50 +0430135hb_parse_double (const char **pp, const char *end, double *pv,
136 bool whole_buffer)
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430137{
Ebrahim Byagowi57f88e12019-09-04 01:20:50 +0430138 return _parse_number<double> (pp, end, pv, whole_buffer,
139 [] (const char *p, char **end)
140 {
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430141#ifdef USE_XLOCALE
Ebrahim Byagowi57f88e12019-09-04 01:20:50 +0430142 return strtod_l (p, end, get_C_locale ());
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430143#else
Ebrahim Byagowi47d82712019-09-06 20:33:10 +0430144 return strtod_rl (p, end);
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430145#endif
Ebrahim Byagowi57f88e12019-09-04 01:20:50 +0430146 });
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430147}