mirror of
				https://github.com/RfidResearchGroup/proxmark3.git
				synced 2025-11-01 00:46:39 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			140 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <assert.h>
 | |
| #include <errno.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <math.h>
 | |
| #ifdef __MINGW32__
 | |
| #undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */
 | |
| #endif
 | |
| #include "jansson_private.h"
 | |
| #include "strbuffer.h"
 | |
| 
 | |
| /* need jansson_private_config.h to get the correct snprintf */
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <jansson_private_config.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef __MINGW32__
 | |
| #define strtod __strtod
 | |
| #endif
 | |
| 
 | |
| #if JSON_HAVE_LOCALECONV
 | |
| #include <locale.h>
 | |
| 
 | |
| /*
 | |
|   - This code assumes that the decimal separator is exactly one
 | |
|     character.
 | |
| 
 | |
|   - If setlocale() is called by another thread between the call to
 | |
|     localeconv() and the call to sprintf() or strtod(), the result may
 | |
|     be wrong. setlocale() is not thread-safe and should not be used
 | |
|     this way. Multi-threaded programs should use uselocale() instead.
 | |
| */
 | |
| 
 | |
| static void to_locale(strbuffer_t *strbuffer) {
 | |
|     const char *point;
 | |
|     char *pos;
 | |
| 
 | |
|     point = localeconv()->decimal_point;
 | |
|     if (*point == '.') {
 | |
|         /* No conversion needed */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     pos = strchr(strbuffer->value, '.');
 | |
|     if (pos)
 | |
|         *pos = *point;
 | |
| }
 | |
| 
 | |
| static void from_locale(char *buffer) {
 | |
|     const char *point;
 | |
|     char *pos;
 | |
| 
 | |
|     point = localeconv()->decimal_point;
 | |
|     if (*point == '.') {
 | |
|         /* No conversion needed */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     pos = strchr(buffer, *point);
 | |
|     if (pos)
 | |
|         *pos = '.';
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int jsonp_strtod(strbuffer_t *strbuffer, double *out) {
 | |
|     double value;
 | |
|     char *end;
 | |
| 
 | |
| #if JSON_HAVE_LOCALECONV
 | |
|     to_locale(strbuffer);
 | |
| #endif
 | |
| 
 | |
|     errno = 0;
 | |
|     value = strtod(strbuffer->value, &end);
 | |
|     assert(end == strbuffer->value + strbuffer->length);
 | |
| 
 | |
|     if ((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
 | |
|         /* Overflow */
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     *out = value;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int jsonp_dtostr(char *buffer, size_t size, double value, int precision) {
 | |
|     int ret;
 | |
|     char *start, *end;
 | |
|     size_t length;
 | |
| 
 | |
|     if (precision == 0)
 | |
|         precision = 17;
 | |
| 
 | |
|     ret = snprintf(buffer, size, "%.*g", precision, value);
 | |
|     if (ret < 0)
 | |
|         return -1;
 | |
| 
 | |
|     length = (size_t)ret;
 | |
|     if (length >= size)
 | |
|         return -1;
 | |
| 
 | |
| #if JSON_HAVE_LOCALECONV
 | |
|     from_locale(buffer);
 | |
| #endif
 | |
| 
 | |
|     /* Make sure there's a dot or 'e' in the output. Otherwise
 | |
|        a real is converted to an integer when decoding */
 | |
|     if (strchr(buffer, '.') == NULL &&
 | |
|             strchr(buffer, 'e') == NULL) {
 | |
|         if (length + 3 >= size) {
 | |
|             /* No space to append ".0" */
 | |
|             return -1;
 | |
|         }
 | |
|         buffer[length] = '.';
 | |
|         buffer[length + 1] = '0';
 | |
|         buffer[length + 2] = '\0';
 | |
|         length += 2;
 | |
|     }
 | |
| 
 | |
|     /* Remove leading '+' from positive exponent. Also remove leading
 | |
|        zeros from exponents (added by some printf() implementations) */
 | |
|     start = strchr(buffer, 'e');
 | |
|     if (start) {
 | |
|         start++;
 | |
|         end = start + 1;
 | |
| 
 | |
|         if (*start == '-')
 | |
|             start++;
 | |
| 
 | |
|         while (*end == '0')
 | |
|             end++;
 | |
| 
 | |
|         if (end != start) {
 | |
|             memmove(start, end, length - (size_t)(end - buffer));
 | |
|             length -= (size_t)(end - start);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (int)length;
 | |
| }
 |