/*
This file is part of GNUnet.
(C) 2005, 2006 Christian Grothoff (and other contributing authors)
GNUnet 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, or (at your
option) any later version.
GNUnet 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 GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/**
* @file util/strings.c
* @brief string functions
* @author Nils Durner
* @author Christian Grothoff
*/
#include "platform.h"
#if HAVE_ICONV
#include <iconv.h>
#endif
#include "gnunet_common.h"
#include "gnunet_strings_lib.h"
#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
/**
* Fill a buffer of the given size with
* count 0-terminated strings (given as varargs).
* If "buffer" is NULL, only compute the amount of
* space required (sum of "strlen(arg)+1").
*
* Unlike using "snprintf" with "%s", this function
* will add 0-terminators after each string. The
* "GNUNET_string_buffer_tokenize" function can be
* used to parse the buffer back into individual
* strings.
*
* @param buffer the buffer to fill with strings, can
* be NULL in which case only the necessary
* amount of space will be calculated
* @param size number of bytes available in buffer
* @param count number of strings that follow
* @param ... count 0-terminated strings to copy to buffer
* @return number of bytes written to the buffer
* (or number of bytes that would have been written)
*/
size_t
GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...)
{
size_t needed;
size_t slen;
const char *s;
va_list ap;
needed = 0;
va_start (ap, count);
while (count > 0)
{
s = va_arg (ap, const char *);
slen = strlen (s) + 1;
if (buffer != NULL)
{
GNUNET_assert (needed + slen <= size);
memcpy (&buffer[needed], s, slen);
}
needed += slen;
count--;
}
va_end (ap);
return needed;
}
/**
* Given a buffer of a given size, find "count"
* 0-terminated strings in the buffer and assign
* the count (varargs) of type "const char**" to the
* locations of the respective strings in the
* buffer.
*
* @param buffer the buffer to parse
* @param size size of the buffer
* @param count number of strings to locate
* @return offset of the character after the last 0-termination
* in the buffer, or 0 on error.
*/
unsigned int
GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size,
unsigned int count, ...)
{
unsigned int start;
unsigned int needed;
const char **r;
va_list ap;
needed = 0;
va_start (ap, count);
while (count > 0)
{
r = va_arg (ap, const char **);
start = needed;
while ((needed < size) && (buffer[needed] != '\0'))
needed++;
if (needed == size)
{
va_end (ap);
return 0; /* error */
}
*r = &buffer[start];
needed++; /* skip 0-termination */
count--;
}
va_end (ap);
return needed;
}
/**
* Convert a given filesize into a fancy human-readable format.
*
* @param size number of bytes
* @return fancy representation of the size (possibly rounded) for humans
*/
char *
GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
{
const char *unit = _( /* size unit */ "b");
char *ret;
if (size > 5 * 1024)
{
size = size / 1024;
unit = "KiB";
if (size > 5 * 1024)
{
size = size / 1024;
unit = "MiB";
if (size > 5 * 1024)
{
size = size / 1024;
unit = "GiB";
if (size > 5 * 1024)
{
size = size / 1024;
unit = "TiB";
}
}
}
}
ret = GNUNET_malloc (32);
GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
return ret;
}
/**
* Convert a given fancy human-readable size to bytes.
*
* @param fancy_size human readable string (i.e. 1 MB)