/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, 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
#include "libpspp/message.h"
#include "libpspp/pool.h"
+#include "gl/c-vasnprintf.h"
#include "gl/relocatable.h"
#include "gl/minmax.h"
#include "gl/xalloc.h"
while (number-- > 0)
{
if (length >= size)
- return false;
+ goto overflow;
buffer[length++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[number % 26];
number /= 26;
}
if (length >= size)
- return false;
+ goto overflow;
buffer[length] = '\0';
buf_reverse (buffer, length);
return true;
+
+overflow:
+ if (length > 0)
+ buffer[0] = '\0';
+ return false;
}
/* Sets the SIZE bytes starting at BLOCK to C,
ss->string = xrealloc (ss->string, size);
}
-/* Makes a pool_alloc_unaligned()'d copy of the contents of OLD
- in POOL, and stores it in NEW. */
+/* Makes a pool_alloc_unaligned()'d, null-terminated copy of the contents of
+ OLD in POOL, and stores it in NEW. */
void
ss_alloc_substring_pool (struct substring *new, struct substring old,
struct pool *pool)
{
- new->string = pool_alloc_unaligned (pool, old.length);
+ new->string = pool_alloc_unaligned (pool, old.length + 1);
new->length = old.length;
memcpy (new->string, old.string, old.length);
+ new->string[old.length] = '\0';
}
/* Allocates room for a CNT-byte string in NEW in POOL. */
ss_tokenize (struct substring ss, struct substring delimiters,
size_t *save_idx, struct substring *token)
{
+ bool found_token;
+
ss_advance (&ss, *save_idx);
*save_idx += ss_ltrim (&ss, delimiters);
ss_get_bytes (&ss, ss_cspan (ss, delimiters), token);
- *save_idx += ss_length (*token) + 1;
- return ss_length (*token) > 0;
+
+ found_token = ss_length (*token) > 0;
+ *save_idx += ss_length (*token) + found_token;
+ return found_token;
}
/* Removes the first CNT bytes from SS. */
return end;
}
+/* Moves the bytes in ST following offset OFS + OLD_LEN in ST to offset OFS +
+ NEW_LEN and returns the byte at offset OFS. The first min(OLD_LEN, NEW_LEN)
+ bytes at the returned position are unchanged; if NEW_LEN > OLD_LEN then the
+ following NEW_LEN - OLD_LEN bytes are initially indeterminate.
+
+ The intention is that the caller should write NEW_LEN bytes at the returned
+ position, to effectively replace the OLD_LEN bytes previously at that
+ position. */
+char *
+ds_splice_uninit (struct string *st,
+ size_t ofs, size_t old_len, size_t new_len)
+{
+ if (new_len != old_len)
+ {
+ if (new_len > old_len)
+ ds_extend (st, ds_length (st) + (new_len - old_len));
+ memmove (ds_data (st) + (ofs + new_len),
+ ds_data (st) + (ofs + old_len),
+ ds_length (st) - (ofs + old_len));
+ st->ss.length += new_len - old_len;
+ }
+ return ds_data (st) + ofs;
+}
+
/* Formats FORMAT as a printf string and appends the result to ST. */
void
ds_put_format (struct string *st, const char *format, ...)
va_end (args);
}
-/* Formats FORMAT as a printf string and appends the result to ST. */
+/* Formats FORMAT as a printf string as if in the C locale and appends the result to ST. */
void
-ds_put_vformat (struct string *st, const char *format, va_list args_)
+ds_put_c_format (struct string *st, const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ ds_put_c_vformat (st, format, args);
+ va_end (args);
+}
+
+
+/* Formats FORMAT as a printf string, using fmt_func (a snprintf like function)
+ and appends the result to ST. */
+static void
+ds_put_vformat_int (struct string *st, const char *format, va_list args_,
+ int (*fmt_func) (char *, size_t, const char *, va_list))
{
int avail, needed;
va_list args;
va_copy (args, args_);
avail = st->ss.string != NULL ? st->capacity - st->ss.length + 1 : 0;
- needed = vsnprintf (st->ss.string + st->ss.length, avail, format, args);
+ needed = fmt_func (st->ss.string + st->ss.length, avail, format, args);
va_end (args);
if (needed >= avail)
{
va_copy (args, args_);
- vsprintf (ds_put_uninit (st, needed), format, args);
+ fmt_func (ds_put_uninit (st, needed), needed + 1, format, args);
va_end (args);
}
else
avail = st->capacity - st->ss.length + 1;
va_copy (args, args_);
- needed = vsnprintf (ds_end (st), avail, format, args);
+ needed = fmt_func (ds_end (st), avail, format, args);
va_end (args);
}
st->ss.length += needed;
}
}
+
+static int
+vasnwrapper (char *str, size_t size, const char *format, va_list ap)
+{
+ c_vasnprintf (str, &size, format, ap);
+ return size;
+}
+
+/* Formats FORMAT as a printf string and appends the result to ST. */
+void
+ds_put_vformat (struct string *st, const char *format, va_list args_)
+{
+ ds_put_vformat_int (st, format, args_, vsnprintf);
+}
+
+/* Formats FORMAT as a printf string, as if in the C locale,
+ and appends the result to ST. */
+void
+ds_put_c_vformat (struct string *st, const char *format, va_list args_)
+{
+ ds_put_vformat_int (st, format, args_, vasnwrapper);
+}
+
/* Appends byte CH to ST. */
void
ds_put_byte (struct string *st, int ch)