Path: blob/master/compat/jansson/strconv.c
1299 views
#include <assert.h>1#include <errno.h>2#include <stdio.h>3#include <string.h>4#include "jansson_private.h"5#include "strbuffer.h"67/* need config.h to get the correct snprintf */8#ifdef HAVE_CONFIG_H9#include <config.h>10#endif1112#if JSON_HAVE_LOCALECONV13#include <locale.h>1415/*16- This code assumes that the decimal separator is exactly one17character.1819- If setlocale() is called by another thread between the call to20localeconv() and the call to sprintf() or strtod(), the result may21be wrong. setlocale() is not thread-safe and should not be used22this way. Multi-threaded programs should use uselocale() instead.23*/2425static void to_locale(strbuffer_t *strbuffer)26{27const char *point;28char *pos;2930point = localeconv()->decimal_point;31if(*point == '.') {32/* No conversion needed */33return;34}3536pos = strchr(strbuffer->value, '.');37if(pos)38*pos = *point;39}4041static void from_locale(char *buffer)42{43const char *point;44char *pos;4546point = localeconv()->decimal_point;47if(*point == '.') {48/* No conversion needed */49return;50}5152pos = strchr(buffer, *point);53if(pos)54*pos = '.';55}56#endif5758int jsonp_strtod(strbuffer_t *strbuffer, double *out)59{60double value;61char *end;6263#if JSON_HAVE_LOCALECONV64to_locale(strbuffer);65#endif6667errno = 0;68value = strtod(strbuffer->value, &end);69assert(end == strbuffer->value + strbuffer->length);7071if(errno == ERANGE && value != 0) {72/* Overflow */73return -1;74}7576*out = value;77return 0;78}7980int jsonp_dtostr(char *buffer, size_t size, double value)81{82int ret;83char *start, *end;84size_t length;8586ret = snprintf(buffer, size, "%.17g", value);87if(ret < 0)88return -1;8990length = (size_t)ret;91if(length >= size)92return -1;9394#if JSON_HAVE_LOCALECONV95from_locale(buffer);96#endif9798/* Make sure there's a dot or 'e' in the output. Otherwise99a real is converted to an integer when decoding */100if(strchr(buffer, '.') == NULL &&101strchr(buffer, 'e') == NULL)102{103if(length + 3 >= size) {104/* No space to append ".0" */105return -1;106}107buffer[length] = '.';108buffer[length + 1] = '0';109buffer[length + 2] = '\0';110length += 2;111}112113/* Remove leading '+' from positive exponent. Also remove leading114zeros from exponents (added by some printf() implementations) */115start = strchr(buffer, 'e');116if(start) {117start++;118end = start + 1;119120if(*start == '-')121start++;122123while(*end == '0')124end++;125126if(end != start) {127memmove(start, end, length - (size_t)(end - buffer));128length -= (size_t)(end - start);129}130}131132return (int)length;133}134135136