1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2
3 /* libcroco - Library for parsing and applying CSS
4 * Copyright (C) 2006-2019 Free Software Foundation, Inc.
5 *
6 * This file is not part of the GNU gettext program, but is used with
7 * GNU gettext.
8 *
9 * The original copyright notice is as follows:
10 */
11
12 /*
13 * This file is part of The Croco Library
14 *
15 * Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of version 2.1 of the GNU Lesser General Public
19 * License as published by the Free Software Foundation.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 * USA
30 *
31 * Author: Dodji Seketeli
32 */
33
34 /**
35 *@CRNum:
36 *
37 *The definition
38 *of the #CRNum class.
39 */
40
41 #include <config.h>
42 #include "cr-num.h"
43 #include "string.h"
44
45 /**
46 * cr_num_new:
47 *
48 *#CRNum.
49 *
50 *Returns the newly built instance of
51 *#CRNum.
52 */
53 CRNum *
cr_num_new(void)54 cr_num_new (void)
55 {
56 CRNum *result = NULL;
57
58 result = g_try_malloc (sizeof (CRNum));
59
60 if (result == NULL) {
61 cr_utils_trace_info ("Out of memory");
62 return NULL;
63 }
64
65 memset (result, 0, sizeof (CRNum));
66
67 return result;
68 }
69
70 /**
71 * cr_num_new_with_val:
72 * @a_val: the numerical value of the number.
73 * @a_type: the type of number.
74 *
75 * A constructor of #CRNum.
76 *
77 * Returns the newly built instance of #CRNum or
78 * NULL if an error arises.
79 */
80 CRNum *
cr_num_new_with_val(gdouble a_val,enum CRNumType a_type)81 cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
82 {
83 CRNum *result = NULL;
84
85 result = cr_num_new ();
86
87 g_return_val_if_fail (result, NULL);
88
89 result->val = a_val;
90 result->type = a_type;
91
92 return result;
93 }
94
95 /**
96 * cr_num_to_string:
97 *@a_this: the current instance of #CRNum.
98 *
99 *Returns the newly built string representation
100 *of the current instance of #CRNum. The returned
101 *string is NULL terminated. The caller *must*
102 *free the returned string.
103 */
104 guchar *
cr_num_to_string(CRNum const * a_this)105 cr_num_to_string (CRNum const * a_this)
106 {
107 gdouble test_val = 0.0;
108
109 guchar *tmp_char1 = NULL,
110 *tmp_char2 = NULL,
111 *result = NULL;
112
113 g_return_val_if_fail (a_this, NULL);
114
115 test_val = a_this->val - (glong) a_this->val;
116
117 if (!test_val) {
118 tmp_char1 = (guchar *) g_strdup_printf ("%ld", (glong) a_this->val);
119 } else {
120 tmp_char1 = (guchar *) g_new0 (char, G_ASCII_DTOSTR_BUF_SIZE + 1);
121 if (tmp_char1 != NULL)
122 g_ascii_dtostr ((gchar *) tmp_char1, G_ASCII_DTOSTR_BUF_SIZE, a_this->val);
123 }
124
125 g_return_val_if_fail (tmp_char1, NULL);
126
127 switch (a_this->type) {
128 case NUM_LENGTH_EM:
129 tmp_char2 = (guchar *) "em";
130 break;
131
132 case NUM_LENGTH_EX:
133 tmp_char2 = (guchar *) "ex";
134 break;
135
136 case NUM_LENGTH_PX:
137 tmp_char2 = (guchar *) "px";
138 break;
139
140 case NUM_LENGTH_IN:
141 tmp_char2 = (guchar *) "in";
142 break;
143
144 case NUM_LENGTH_CM:
145 tmp_char2 = (guchar *) "cm";
146 break;
147
148 case NUM_LENGTH_MM:
149 tmp_char2 = (guchar *) "mm";
150 break;
151
152 case NUM_LENGTH_PT:
153 tmp_char2 = (guchar *) "pt";
154 break;
155
156 case NUM_LENGTH_PC:
157 tmp_char2 = (guchar *) "pc";
158 break;
159
160 case NUM_ANGLE_DEG:
161 tmp_char2 = (guchar *) "deg";
162 break;
163
164 case NUM_ANGLE_RAD:
165 tmp_char2 = (guchar *) "rad";
166 break;
167
168 case NUM_ANGLE_GRAD:
169 tmp_char2 = (guchar *) "grad";
170 break;
171
172 case NUM_TIME_MS:
173 tmp_char2 = (guchar *) "ms";
174 break;
175
176 case NUM_TIME_S:
177 tmp_char2 = (guchar *) "s";
178 break;
179
180 case NUM_FREQ_HZ:
181 tmp_char2 = (guchar *) "Hz";
182 break;
183
184 case NUM_FREQ_KHZ:
185 tmp_char2 = (guchar *) "KHz";
186 break;
187
188 case NUM_PERCENTAGE:
189 tmp_char2 = (guchar *) "%";
190 break;
191 case NUM_INHERIT:
192 tmp_char2 = (guchar *) "inherit";
193 break ;
194 case NUM_AUTO:
195 tmp_char2 = (guchar *) "auto";
196 break ;
197 case NUM_GENERIC:
198 tmp_char2 = NULL ;
199 break ;
200 default:
201 tmp_char2 = (guchar *) "unknown";
202 break;
203 }
204
205 if (tmp_char2) {
206 result = (guchar *) g_strconcat ((gchar *) tmp_char1, tmp_char2, NULL);
207 g_free (tmp_char1);
208 } else {
209 result = tmp_char1;
210 }
211
212 return result;
213 }
214
215 /**
216 * cr_num_copy:
217 *@a_src: the instance of #CRNum to copy.
218 *Must be non NULL.
219 *@a_dest: the destination of the copy.
220 *Must be non NULL
221 *
222 *Copies an instance of #CRNum.
223 *
224 *Returns CR_OK upon successful completion, an
225 *error code otherwise.
226 */
227 enum CRStatus
cr_num_copy(CRNum * a_dest,CRNum const * a_src)228 cr_num_copy (CRNum * a_dest, CRNum const * a_src)
229 {
230 g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
231
232 memcpy (a_dest, a_src, sizeof (CRNum));
233
234 return CR_OK;
235 }
236
237 /**
238 * cr_num_dup:
239 *@a_this: the instance of #CRNum to duplicate.
240 *
241 *Duplicates an instance of #CRNum
242 *
243 *Returns the newly created (duplicated) instance of #CRNum.
244 *Must be freed by cr_num_destroy().
245 */
246 CRNum *
cr_num_dup(CRNum const * a_this)247 cr_num_dup (CRNum const * a_this)
248 {
249 CRNum *result = NULL;
250 enum CRStatus status = CR_OK;
251
252 g_return_val_if_fail (a_this, NULL);
253
254 result = cr_num_new ();
255 g_return_val_if_fail (result, NULL);
256
257 status = cr_num_copy (result, a_this);
258 g_return_val_if_fail (status == CR_OK, NULL);
259
260 return result;
261 }
262
263 /**
264 * cr_num_set:
265 *Sets an instance of #CRNum.
266 *@a_this: the current instance of #CRNum to be set.
267 *@a_val: the new numerical value to be hold by the current
268 *instance of #CRNum
269 *@a_type: the new type of #CRNum.
270 *
271 * Returns CR_OK upon succesful completion, an error code otherwise.
272 */
273 enum CRStatus
cr_num_set(CRNum * a_this,gdouble a_val,enum CRNumType a_type)274 cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
275 {
276 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
277
278 a_this->val = a_val;
279 a_this->type = a_type;
280
281 return CR_OK;
282 }
283
284 /**
285 * cr_num_is_fixed_length:
286 * @a_this: the current instance of #CRNum .
287 *
288 *Tests if the current instance of #CRNum is a fixed
289 *length value or not. Typically a fixed length value
290 *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
291 *See the definition of #CRNumType to see what we mean.
292 *
293 *Returns TRUE if the instance of #CRNum is a fixed length number,
294 *FALSE otherwise.
295 */
296 gboolean
cr_num_is_fixed_length(CRNum const * a_this)297 cr_num_is_fixed_length (CRNum const * a_this)
298 {
299 gboolean result = FALSE;
300
301 g_return_val_if_fail (a_this, FALSE);
302
303 if (a_this->type >= NUM_LENGTH_EM
304 && a_this->type <= NUM_LENGTH_PC) {
305 result = TRUE ;
306 }
307 return result ;
308 }
309
310 /**
311 * cr_num_destroy:
312 *@a_this: the this pointer of
313 *the current instance of #CRNum.
314 *
315 *The destructor of #CRNum.
316 */
317 void
cr_num_destroy(CRNum * a_this)318 cr_num_destroy (CRNum * a_this)
319 {
320 g_return_if_fail (a_this);
321
322 g_free (a_this);
323 }
324