aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/lib/eina_convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/lib/eina_convert.c')
-rw-r--r--libraries/eina/src/lib/eina_convert.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/libraries/eina/src/lib/eina_convert.c b/libraries/eina/src/lib/eina_convert.c
new file mode 100644
index 0000000..63b6654
--- /dev/null
+++ b/libraries/eina/src/lib/eina_convert.c
@@ -0,0 +1,483 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric BAIL, Vincent Torri
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <math.h>
24#include <stdlib.h>
25#include <string.h>
26#include <stdio.h>
27
28#ifdef HAVE_EVIL
29# include <Evil.h>
30#endif
31
32#include "eina_config.h"
33#include "eina_private.h"
34#include "eina_log.h"
35
36/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
37#include "eina_safety_checks.h"
38#include "eina_convert.h"
39#include "eina_fp.h"
40
41/*============================================================================*
42* Local *
43*============================================================================*/
44
45/**
46 * @cond LOCAL
47 */
48
49static const char look_up_table[] = {'0', '1', '2', '3', '4',
50 '5', '6', '7', '8', '9',
51 'a', 'b', 'c', 'd', 'e', 'f'};
52static int _eina_convert_log_dom = -1;
53
54#ifdef ERR
55#undef ERR
56#endif
57#define ERR(...) EINA_LOG_DOM_ERR(_eina_convert_log_dom, __VA_ARGS__)
58
59#ifdef DBG
60#undef DBG
61#endif
62#define DBG(...) EINA_LOG_DOM_DBG(_eina_convert_log_dom, __VA_ARGS__)
63
64#define HEXA_TO_INT(Hexa) (Hexa >= 'a') ? Hexa - 'a' + 10 : Hexa - '0'
65
66static inline void reverse(char s[], int length)
67{
68 int i, j;
69 char c;
70
71 for (i = 0, j = length - 1; i < j; i++, j--)
72 {
73 c = s[i];
74 s[i] = s[j];
75 s[j] = c;
76 }
77}
78
79/**
80 * @endcond
81 */
82
83/*============================================================================*
84* Global *
85*============================================================================*/
86
87/**
88 * @cond LOCAL
89 */
90
91EAPI Eina_Error EINA_ERROR_CONVERT_P_NOT_FOUND = 0;
92EAPI Eina_Error EINA_ERROR_CONVERT_0X_NOT_FOUND = 0;
93EAPI Eina_Error EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = 0;
94
95static const char EINA_ERROR_CONVERT_0X_NOT_FOUND_STR[] =
96 "Error during string conversion to float, First '0x' was not found.";
97static const char EINA_ERROR_CONVERT_P_NOT_FOUND_STR[] =
98 "Error during string conversion to float, First 'p' was not found.";
99static const char EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH_STR[] =
100 "Error outrun string limit during conversion string conversion to float.";
101
102/**
103 * @endcond
104 */
105
106/**
107 * @internal
108 * @brief Initialize the convert module.
109 *
110 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
111 *
112 * This function sets up the convert module of Eina. It is called by
113 * eina_init().
114 *
115 * This function sets up the error module of Eina and registers the
116 * errors #EINA_ERROR_CONVERT_0X_NOT_FOUND,
117 * #EINA_ERROR_CONVERT_P_NOT_FOUND and
118 * #EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH.
119 *
120 * @see eina_init()
121 */
122Eina_Bool
123eina_convert_init(void)
124{
125 _eina_convert_log_dom = eina_log_domain_register("eina_convert",
126 EINA_LOG_COLOR_DEFAULT);
127 if (_eina_convert_log_dom < 0)
128 {
129 EINA_LOG_ERR("Could not register log domain: eina_convert");
130 return EINA_FALSE;
131 }
132
133#define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
134 EEMR(EINA_ERROR_CONVERT_0X_NOT_FOUND);
135 EEMR(EINA_ERROR_CONVERT_P_NOT_FOUND);
136 EEMR(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
137#undef EEMR
138
139 return EINA_TRUE;
140}
141
142/**
143 * @internal
144 * @brief Shut down the convert module.
145 *
146 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
147 *
148 * This function shuts down the convert module set up by
149 * eina_convert_init(). It is called by eina_shutdown().
150 *
151 * @see eina_shutdown()
152 */
153Eina_Bool
154eina_convert_shutdown(void)
155{
156 eina_log_domain_unregister(_eina_convert_log_dom);
157 _eina_convert_log_dom = -1;
158 return EINA_TRUE;
159}
160
161/*============================================================================*
162* API *
163*============================================================================*/
164
165/*
166 * Come from the second edition of The C Programming Language ("K&R2") on page 64
167 */
168
169EAPI int
170eina_convert_itoa(int n, char *s)
171{
172 int i = 0;
173 int r = 0;
174
175 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
176
177 if (n < 0)
178 {
179 n = -n;
180 *s++ = '-';
181 r = 1;
182 }
183
184 do {
185 s[i++] = n % 10 + '0';
186 } while ((n /= 10) > 0);
187
188 s[i] = '\0';
189
190 reverse(s, i);
191
192 return i + r;
193}
194
195EAPI int
196eina_convert_xtoa(unsigned int n, char *s)
197{
198 int i;
199
200 EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0);
201
202 i = 0;
203 do {
204 s[i++] = look_up_table[n & 0xF];
205 } while ((n >>= 4) > 0);
206
207 s[i] = '\0';
208
209 reverse(s, i);
210
211 return i;
212}
213
214EAPI Eina_Bool
215eina_convert_atod(const char *src, int length, long long *m, long *e)
216{
217 const char *str = src;
218 long long mantisse;
219 long exponent;
220 int nbr_decimals = 0;
221 int sign = 1;
222
223 EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
226
227 if (length <= 0)
228 goto on_length_error;
229
230 /* Compute the mantisse. */
231 if (*str == '-')
232 {
233 sign = -1;
234 str++;
235 length--;
236 }
237
238 if (length <= 2)
239 goto on_length_error;
240
241 if (strncmp(str, "0x", 2))
242 {
243 eina_error_set(EINA_ERROR_CONVERT_0X_NOT_FOUND);
244 DBG("'0x' not found in '%s'", src);
245 return EINA_FALSE;
246 }
247
248 str += 2;
249 length -= 2;
250
251 mantisse = HEXA_TO_INT(*str);
252
253 str++;
254 length--; if (length <= 0)
255 goto on_length_error;
256
257 if (*str == '.')
258 for (str++, length--;
259 length > 0 && *str != 'p';
260 ++str, --length, ++nbr_decimals)
261 {
262 mantisse <<= 4;
263 mantisse += HEXA_TO_INT(*str);
264 }
265
266 if (sign < 0)
267 mantisse = -mantisse;
268
269 /* Compute the exponent. */
270 if (*str != 'p')
271 {
272 eina_error_set(EINA_ERROR_CONVERT_P_NOT_FOUND);
273 DBG("'p' not found in '%s'", src);
274 return EINA_FALSE;
275 }
276
277 sign = +1;
278
279 str++;
280 length--; if (length <= 0)
281 goto on_length_error;
282
283 if (strchr("-+", *str))
284 {
285 sign = (*str == '-') ? -1 : +1;
286
287 str++; length--;
288 }
289
290 for (exponent = 0; length > 0 && *str != '\0'; ++str, --length)
291 {
292 exponent *= 10;
293 exponent += *str - '0';
294 }
295
296 if (length < 0)
297 goto on_length_error;
298
299 if (sign < 0)
300 exponent = -exponent;
301
302 *m = mantisse;
303 *e = exponent - (nbr_decimals << 2);
304
305 return EINA_TRUE;
306
307on_length_error:
308 eina_error_set(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH);
309 return EINA_FALSE;
310}
311
312EAPI int
313eina_convert_dtoa(double d, char *des)
314{
315 int length = 0;
316 int p;
317 int i;
318
319 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
320
321 if (d < 0.0)
322 {
323 *(des++) = '-';
324 d = -d;
325 length++;
326 }
327
328 d = frexp(d, &p);
329
330 if (p)
331 {
332 d *= 2;
333 p -= 1;
334 }
335
336 *(des++) = '0';
337 *(des++) = 'x';
338 *(des++) = look_up_table[(size_t)d];
339 *(des++) = '.';
340 length += 4;
341
342 for (i = 0; i < 16; i++, length++)
343 {
344 d -= floor(d);
345 d *= 16;
346 *(des++) = look_up_table[(size_t)d];
347 }
348
349 while (*(des - 1) == '0')
350 {
351 des--;
352 length--;
353 }
354
355 if (*(des - 1) == '.')
356 {
357 des--;
358 length--;
359 }
360
361 *(des++) = 'p';
362 if (p < 0)
363 {
364 *(des++) = '-';
365 p = -p;
366 }
367 else
368 *(des++) = '+';
369
370 length += 2;
371
372 return length + eina_convert_itoa(p, des);
373}
374
375EAPI int
376eina_convert_fptoa(Eina_F32p32 fp, char *des)
377{
378 int length = 0;
379 int p = 0;
380 int i;
381
382 EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE);
383
384 if (fp == 0)
385 {
386 memcpy(des, "0x0p+0", 7);
387 return 7;
388 }
389
390 if (fp < 0)
391 {
392 *(des++) = '-';
393 fp = -fp;
394 length++;
395 }
396
397 /* fp >= 1 */
398 if (fp >= 0x0000000100000000LL)
399 while (fp >= 0x0000000100000000LL)
400 {
401 p++;
402 /* fp /= 2 */
403 fp >>= 1;
404 } /* fp < 0.5 */
405 else if (fp < 0x80000000)
406 while (fp < 0x80000000)
407 {
408 p--;
409 /* fp *= 2 */
410 fp <<= 1;
411 }
412
413 if (p)
414 {
415 p--;
416 /* fp *= 2 */
417 fp <<= 1;
418 }
419
420 *(des++) = '0';
421 *(des++) = 'x';
422 *(des++) = look_up_table[fp >> 32];
423 *(des++) = '.';
424 length += 4;
425
426 for (i = 0; i < 16; i++, length++)
427 {
428 fp &= 0x00000000ffffffffLL;
429 fp <<= 4; /* fp *= 16 */
430 *(des++) = look_up_table[fp >> 32];
431 }
432
433 while (*(des - 1) == '0')
434 {
435 des--;
436 length--;
437 }
438
439 if (*(des - 1) == '.')
440 {
441 des--;
442 length--;
443 }
444
445 *(des++) = 'p';
446 if (p < 0)
447 {
448 *(des++) = '-';
449 p = -p;
450 }
451 else
452 *(des++) = '+';
453
454 length += 2;
455
456 return length + eina_convert_itoa(p, des);
457}
458
459EAPI Eina_Bool
460eina_convert_atofp(const char *src, int length, Eina_F32p32 *fp)
461{
462 long long m;
463 long e;
464
465 if (!eina_convert_atod(src, length, &m, &e))
466 return EINA_FALSE;
467
468 if (!fp)
469 return EINA_TRUE;
470
471 e += 32;
472
473 if (e > 0)
474 *fp = m << e;
475 else
476 *fp = m >> -e;
477
478 return EINA_TRUE;
479}
480
481/**
482 * @}
483 */