mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-29 17:38:59 +00:00
144 lines
7.2 KiB
C
144 lines
7.2 KiB
C
/*
|
|
Serval numerical string primitives
|
|
Copyright (C) 2012-2015 Serval Project Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef __SERVAL_DNA__NUMERIC_STR_H__
|
|
#define __SERVAL_DNA__NUMERIC_STR_H__
|
|
|
|
#include "strbuf.h"
|
|
#include <sys/types.h> // for size_t
|
|
#include <stdint.h>
|
|
|
|
#ifndef __SERVAL_DNA__NUMERIC_STR_INLINE
|
|
# if __GNUC__ && !__GNUC_STDC_INLINE__
|
|
# define __SERVAL_DNA__NUMERIC_STR_INLINE extern inline
|
|
# else
|
|
# define __SERVAL_DNA__NUMERIC_STR_INLINE inline
|
|
# endif
|
|
#endif
|
|
|
|
/* Returns 1 if the given nul-terminated string parses successfully as an unsigned 64-bit integer.
|
|
* Returns 0 if not. This is simply a shortcut for str_to_uint32(str, 10, NULL, NULL), which is
|
|
* convenient for when a pointer to a predicate function is needed.
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
int str_is_uint64_decimal(const char *str);
|
|
|
|
/* Parse a NUL-terminated string as an integer in ASCII radix notation in the given 'base' (eg,
|
|
* base=10 means decimal).
|
|
*
|
|
* Returns 1 if a valid integer is parsed, storing the value in *result (unless result is NULL) and
|
|
* storing a pointer to the immediately succeeding character in *afterp. If afterp is NULL then
|
|
* returns 0 unless the immediately succeeding character is a NUL '\0'. If no integer is parsed or
|
|
* if the integer overflows (too many digits), then returns 0, leaving *result unchanged and setting
|
|
* setting *afterp to point to the character where parsing failed.
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
int str_to_uint16(const char *str, unsigned base, uint16_t *result, const char **afterp);
|
|
int str_to_int32(const char *str, unsigned base, int32_t *result, const char **afterp);
|
|
int str_to_uint32(const char *str, unsigned base, uint32_t *result, const char **afterp);
|
|
int str_to_int64(const char *str, unsigned base, int64_t *result, const char **afterp);
|
|
int str_to_uint64(const char *str, unsigned base, uint64_t *result, const char **afterp);
|
|
|
|
/* Parse a length-bound string as an integer in ASCII radix notation in the given 'base' (eg,
|
|
* base=10 means decimal).
|
|
*
|
|
* Returns 1 if a valid integer is parsed, storing the value in *result (unless result is NULL) and
|
|
* storing a pointer to the immediately succeeding character in *afterp. If afterp is NULL then
|
|
* returns 0 unless all 'strlen' characters of the string were consumed. If no integer is parsed or
|
|
* if the integer overflows (too many digits), then returns 0, leaving *result unchanged and setting
|
|
* setting *afterp to point to the character where parsing failed.
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
int strn_to_uint16(const char *str, size_t strlen, unsigned base, uint16_t *result, const char **afterp);
|
|
int strn_to_uint32(const char *str, size_t strlen, unsigned base, uint32_t *result, const char **afterp);
|
|
int strn_to_uint64(const char *str, size_t strlen, unsigned base, uint64_t *result, const char **afterp);
|
|
|
|
/* Parse a string as an integer in ASCII radix notation in the given 'base' (eg, base=10 means
|
|
* decimal) and scale the result by a factor given by an optional suffix "scaling" character in the
|
|
* set {kKmMgG}: 'k' = 1e3, 'K' = 1<<10, 'm' = 1e6, 'M' = 1<<20, 'g' = 1e9, 'G' = * 1<<30.
|
|
*
|
|
* Return 1 if a valid scaled integer was parsed, storing the value in *result (unless result is
|
|
* NULL) and storing a pointer to the immediately succeeding character in *afterp (unless afterp is
|
|
* NULL, in which case returns 1 only if the immediately succeeding character is a nul '\0').
|
|
* Returns 0 otherwise, leaving *result and *afterp unchanged.
|
|
*
|
|
* NOTE: an argument base > 16 will cause any trailing 'g' or 'G' character to be parsed as part of
|
|
* the integer, not as a scale suffix. Ditto for base > 20 and 'k' 'K', and base > 22 and 'm' 'M'.
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
int str_to_int32_scaled(const char *str, unsigned base, int32_t *result, const char **afterp);
|
|
int str_to_uint32_scaled(const char *str, unsigned base, uint32_t *result, const char **afterp);
|
|
int str_to_int64_scaled(const char *str, unsigned base, int64_t *result, const char **afterp);
|
|
int str_to_uint64_scaled(const char *str, unsigned base, uint64_t *result, const char **afterp);
|
|
uint64_t scale_factor(const char *str, const char **afterp);
|
|
|
|
/* Append an integer value to a strbuf in ASCII decimal format, optionally scaled with a scale
|
|
* suffix character in the set {kKmMgGtTpP}: 'k' = 1e3, 'K' = 1<<10, 'm' = 1e6, 'M' = 1<<20, 'g' =
|
|
* 1e9, 'G' = * 1<<30, etc. This format is lossless because the value is only scaled if it is an
|
|
* exact multiple of the scaling factor.
|
|
*
|
|
* Eg, 1000 -> "1k"
|
|
* 1001 -> "1001"
|
|
* 1024 -> "1K"
|
|
* 1025 -> "1025"
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
strbuf strbuf_append_uint32_scaled(strbuf sb, uint32_t value);
|
|
strbuf strbuf_append_uint64_scaled(strbuf sb, uint64_t value);
|
|
|
|
/* Append a double value to a strbuf in ASCII decimal fixed-point format with three significant
|
|
* digits, optionally scaled with either a binary scale suffix in the set {KMGTP}: 'K' = 1<<10, 'M'
|
|
* = 1<<20, 'G' = * 1<<30, etc., or an S.I. scale suffix in the set {kmgtp}: 'k' = 1e3, 'm' = 1e6,
|
|
* etc. This format is lossy because it always applies the scale, which may truncate insignificant
|
|
* digits.
|
|
*
|
|
* Eg, binary S.I.
|
|
* 1000 -> "1000" 1000 -> "1.00k"
|
|
* 1001 -> "1001" 1001 -> "1.00k"
|
|
* 1024 -> "1.00K" 1024 -> "1.02k"
|
|
* 1025 -> "1.00K" 1025 -> "1.03k"
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
strbuf strbuf_append_double_scaled_binary(strbuf sb, double value);
|
|
strbuf strbuf_append_double_scaled_si(strbuf sb, double value);
|
|
|
|
#define alloca_double_scaled_binary(v) strbuf_str(strbuf_append_double_scaled_binary(strbuf_alloca(10), (v)))
|
|
#define alloca_double_scaled_si(v) strbuf_str(strbuf_append_double_scaled_si(strbuf_alloca(10), (v)))
|
|
|
|
/* Parse a string as a time interval (seconds) in millisecond resolution. Return the number of
|
|
* milliseconds. Valid strings are all unsigned ASCII decimal numbers with up to three digits after
|
|
* the decimal point.
|
|
*
|
|
* Return 1 if a valid interval was parsed, storing the number of milliseconds in *result (unless
|
|
* result is NULL) and storing a pointer to the immediately succeeding character in *afterp (unless
|
|
* afterp is NULL, in which case returns 1 only if the immediately succeeding character is a nul
|
|
* '\0'). Returns 0 otherwise, leaving *result and *afterp unchanged.
|
|
*
|
|
* @author Andrew Bettison <andrew@servalproject.com>
|
|
*/
|
|
int str_to_uint64_interval_ms(const char *str, int64_t *result, const char **afterp);
|
|
|
|
#endif // __SERVAL_DNA__NUMERIC_STR_H__
|