From 538bc87998624377ba72589a0ee68e4527f82489 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sat, 24 Oct 2009 00:17:57 +0200 Subject: [PATCH] Add dehumanize_number function Taken from NetBSD. --- Makefile | 1 + Versions | 2 + include/bsd/stdlib.h | 6 +++ src/dehumanize_number.c | 114 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 src/dehumanize_number.c diff --git a/Makefile b/Makefile index 4294b4a..4465a2d 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ LIB_SRCS := \ fgetln.c \ heapsort.c \ humanize_number.c \ + dehumanize_number.c \ inet_net_pton.c \ hash/md5.c hash/md5hl.c \ setmode.c \ diff --git a/Versions b/Versions index 3e99cf4..74a459f 100644 --- a/Versions +++ b/Versions @@ -47,5 +47,7 @@ LIBBSD_0.2 { strnvis; strnunvis; + + dehumanize_number; } LIBBSD_0.1; diff --git a/include/bsd/stdlib.h b/include/bsd/stdlib.h index 3e1fe83..453c33d 100644 --- a/include/bsd/stdlib.h +++ b/include/bsd/stdlib.h @@ -31,9 +31,15 @@ #include #include +#include #include +/* For compatibility with NetBSD, which defines humanize_number here. */ +#include + __BEGIN_DECLS +int dehumanize_number(const char *str, int64_t *size); + const char *fmtcheck (const char *, const char *); char *getprogname (); diff --git a/src/dehumanize_number.c b/src/dehumanize_number.c new file mode 100644 index 0000000..4884422 --- /dev/null +++ b/src/dehumanize_number.c @@ -0,0 +1,114 @@ +/* $NetBSD: dehumanize_number.c,v 1.2 2007/12/14 17:32:47 xtraeme Exp $ */ + +/* + * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal, developed as part of Google's Summer of Code + * 2005 program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: dehumanize_number.c,v 1.2 2007/12/14 17:32:47 xtraeme Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include + +/* + * Converts the number given in 'str', which may be given in a humanized + * form (as described in humanize_number(3), but with some limitations), + * to an int64_t without units. + * In case of success, 0 is returned and *size holds the value. + * Otherwise, -1 is returned and *size is untouched. + * + * TODO: Internationalization, SI units. + */ +int +dehumanize_number(const char *str, int64_t *size) +{ + char *ep, unit; + const char *delimit; + long multiplier; + long long tmp, tmp2; + size_t len; + + len = strlen(str); + if (len == 0) { + errno = EINVAL; + return -1; + } + + multiplier = 1; + + unit = str[len - 1]; + if (isalpha((unsigned char)unit)) { + switch (tolower((unsigned char)unit)) { + case 'b': + multiplier = 1; + break; + + case 'k': + multiplier = 1024; + break; + + case 'm': + multiplier = 1024 * 1024; + break; + + case 'g': + multiplier = 1024 * 1024 * 1024; + break; + + default: + errno = EINVAL; + return -1; /* Invalid suffix. */ + } + + delimit = &str[len - 1]; + } else + delimit = NULL; + + errno = 0; + tmp = strtoll(str, &ep, 10); + if (str[0] == '\0' || (ep != delimit && *ep != '\0')) + return -1; /* Not a number. */ + else if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN)) + return -1; /* Out of range. */ + + tmp2 = tmp * multiplier; + tmp2 = tmp2 / multiplier; + if (tmp != tmp2) { + errno = ERANGE; + return -1; /* Out of range. */ + } + *size = tmp * multiplier; + + return 0; +}