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