/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010 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 <stdint.h>
#include <stdlib.h>
+#include <libpspp/cast.h>
#include <libpspp/message.h>
#include <libpspp/pool.h>
/* Copies string SRC to buffer DST, of size DST_SIZE bytes.
DST is truncated to DST_SIZE bytes or padded on the right with
- spaces as needed. */
+ copies of PAD as needed. */
void
-buf_copy_str_rpad (char *dst, size_t dst_size, const char *src)
+buf_copy_str_rpad (char *dst, size_t dst_size, const char *src, char pad)
{
size_t src_len = strlen (src);
if (src_len >= dst_size)
else
{
memcpy (dst, src, src_len);
- memset (&dst[src_len], ' ', dst_size - src_len);
+ memset (&dst[src_len], pad, dst_size - src_len);
}
}
/* Copies string SRC to buffer DST, of size DST_SIZE bytes.
DST is truncated to DST_SIZE bytes or padded on the left with
- spaces as needed. */
+ copies of PAD as needed. */
void
-buf_copy_str_lpad (char *dst, size_t dst_size, const char *src)
+buf_copy_str_lpad (char *dst, size_t dst_size, const char *src, char pad)
{
size_t src_len = strlen (src);
if (src_len >= dst_size)
else
{
size_t pad_cnt = dst_size - src_len;
- memset (&dst[0], ' ', pad_cnt);
+ memset (&dst[0], pad, pad_cnt);
memcpy (dst + pad_cnt, src, src_len);
}
}
/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
DST is truncated to DST_SIZE bytes or padded on the left with
- spaces as needed. */
+ copies of PAD as needed. */
void
buf_copy_lpad (char *dst, size_t dst_size,
- const char *src, size_t src_size)
+ const char *src, size_t src_size,
+ char pad)
{
if (src_size >= dst_size)
memmove (dst, src, dst_size);
else
{
- memset (dst, ' ', dst_size - src_size);
+ memset (dst, pad, dst_size - src_size);
memmove (&dst[dst_size - src_size], src, src_size);
}
}
/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
DST is truncated to DST_SIZE bytes or padded on the right with
- spaces as needed. */
+ copies of PAD as needed. */
void
buf_copy_rpad (char *dst, size_t dst_size,
- const char *src, size_t src_size)
+ const char *src, size_t src_size,
+ char pad)
{
if (src_size >= dst_size)
memmove (dst, src, dst_size);
else
{
memmove (dst, src, src_size);
- memset (&dst[src_size], ' ', dst_size - src_size);
+ memset (&dst[src_size], pad, dst_size - src_size);
}
}
st->ss.length = new_length;
}
+/* Removes N characters from ST starting at offset START. */
+void
+ds_remove (struct string *st, size_t start, size_t n)
+{
+ if (n > 0 && start < st->ss.length)
+ {
+ if (st->ss.length - start <= n)
+ {
+ /* All characters at or beyond START are deleted. */
+ st->ss.length = start;
+ }
+ else
+ {
+ /* Some characters remain and must be shifted into
+ position. */
+ memmove (st->ss.string + st->ss.length,
+ st->ss.string + st->ss.length + n,
+ st->ss.length - start - n);
+ st->ss.length -= n;
+ }
+ }
+ else
+ {
+ /* There are no characters to delete or no characters at or
+ beyond START, hence deletion is a no-op. */
+ }
+}
+
/* Returns true if ST is empty, false otherwise. */
bool
ds_is_empty (const struct string *st)
char *
ds_cstr (const struct string *st_)
{
- struct string *st = (struct string *) st_;
+ struct string *st = CONST_CAST (struct string *, st_);
if (st->ss.string == NULL)
ds_extend (st, 1);
st->ss.string[st->ss.length] = '\0';
return st->ss.string;
}
+/* Returns the value of ST as a null-terminated string and then
+ reinitialized ST as an empty string. The caller must free the
+ returned string with free(). */
+char *
+ds_steal_cstr (struct string *st)
+{
+ char *s = ds_cstr (st);
+ ds_init_empty (st);
+ return s;
+}
+
/* Reads characters from STREAM and appends them to ST, stopping
after MAX_LENGTH characters, after appending a newline, or
after an I/O error or end of file was encountered, whichever
to ST, false if no characters were read before an I/O error or
end of file (or if MAX_LENGTH was 0).
- This function accepts LF, CR LF, and CR sequences as new-line,
- and translates each of them to a single '\n' new-line
- character in ST. */
+ This function treats LF and CR LF sequences as new-line,
+ translating each of them to a single '\n' new-line character
+ in ST. */
bool
ds_read_line (struct string *st, FILE *stream, size_t max_length)
{
for (length = 0; length < max_length; length++)
{
int c = getc (stream);
- if (c == EOF)
- break;
-
- if (c == '\r')
+ switch (c)
{
+ case EOF:
+ return length > 0;
+
+ case '\n':
+ ds_put_char (st, c);
+ return true;
+
+ case '\r':
c = getc (stream);
- if (c != '\n')
+ if (c == '\n')
+ {
+ /* CR followed by LF is special: translate to \n. */
+ ds_put_char (st, '\n');
+ return true;
+ }
+ else
{
+ /* CR followed by anything else is just CR. */
+ ds_put_char (st, '\r');
+ if (c == EOF)
+ return true;
ungetc (c, stream);
- c = '\n';
}
+ break;
+
+ default:
+ ds_put_char (st, c);
}
- ds_put_char (st, c);
- if (c == '\n')
- return true;
}
return length > 0;
free ((char *) rel);
}
}
+
+
+\f
+
+/* Operations on uint8_t "strings" */
+
+/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
+ DST is truncated to DST_SIZE bytes or padded on the right with
+ copies of PAD as needed. */
+void
+u8_buf_copy_rpad (uint8_t *dst, size_t dst_size,
+ const uint8_t *src, size_t src_size,
+ char pad)
+{
+ if (src_size >= dst_size)
+ memmove (dst, src, dst_size);
+ else
+ {
+ memmove (dst, src, src_size);
+ memset (&dst[src_size], pad, dst_size - src_size);
+ }
+}