X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fstr.c;h=9f0cb6e31463ab5caf319114e43fed26f640ae2b;hb=131ca96f8e1b8675e80b37ad6cedca1b21b87e87;hp=d082672060f5235d6610939221365663fb5652b8;hpb=5165d8c7ed098d87a481f08652f3e1aa6d82c366;p=pspp diff --git a/src/libpspp/str.c b/src/libpspp/str.c index d082672060..9f0cb6e314 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 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 @@ -23,11 +23,14 @@ #include #include +#include #include #include +#include #include "minmax.h" #include "xalloc.h" +#include "xmemdup0.h" #include "xsize.h" /* Reverses the order of NBYTES bytes at address P, thus converting @@ -124,9 +127,9 @@ str_compare_rpad (const char *a, const char *b) /* 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) @@ -134,15 +137,15 @@ buf_copy_str_rpad (char *dst, size_t dst_size, const char *src) 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) @@ -150,40 +153,42 @@ buf_copy_str_lpad (char *dst, size_t dst_size, const char *src) 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); } } @@ -375,14 +380,13 @@ ss_tail (struct substring ss, size_t cnt) return ss; } -/* Makes a malloc()'d copy of the contents of OLD +/* Makes a malloc()'d, null-terminated copy of the contents of OLD and stores it in NEW. */ void ss_alloc_substring (struct substring *new, struct substring old) { - new->string = xmalloc (old.length); + new->string = xmemdup0 (old.string, old.length); new->length = old.length; - memcpy (new->string, old.string, old.length); } /* Allocates room for a CNT-character string in NEW. */ @@ -1068,6 +1072,34 @@ ds_set_length (struct string *st, size_t new_length, char pad) 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) @@ -1183,55 +1215,75 @@ ds_capacity (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; } -/* Appends to ST a newline-terminated line read from STREAM, but - no more than MAX_LENGTH characters. - Newline is the last character of ST on return, if encountering - a newline was the reason for terminating. - Returns true if at least one character was read from STREAM - and appended to ST, false if no characters at all were read - before an I/O error or end of file was encountered (or - MAX_LENGTH was 0). */ +/* 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 + comes first. Returns true if at least one character was added + 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 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) { - if (!st->ss.length && max_length == SIZE_MAX) - { - size_t capacity = st->capacity ? st->capacity + 1 : 0; - ssize_t n = getline (&st->ss.string, &capacity, stream); - if (capacity) - st->capacity = capacity - 1; - if (n > 0) - { - st->ss.length = n; - return true; - } - else - return false; - } - else - { - size_t length; + size_t length; - for (length = 0; length < max_length; length++) + for (length = 0; length < max_length; length++) + { + int c = getc (stream); + switch (c) { - int c = getc (stream); - if (c == EOF) - break; + case EOF: + return length > 0; + case '\n': ds_put_char (st, c); + return true; + + case '\r': + c = getc (stream); if (c == '\n') - return true; + { + /* 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); + } + break; + + default: + ds_put_char (st, c); } - - return length > 0; } + + return length > 0; } /* Removes a comment introduced by `#' from ST, @@ -1399,3 +1451,44 @@ ds_put_char_multiple (struct string *st, int ch, size_t cnt) { memset (ds_put_uninit (st, cnt), ch, cnt); } + + +/* If relocation has been enabled, replace ST, + with its relocated version */ +void +ds_relocate (struct string *st) +{ + const char *orig = ds_cstr (st); + const char *rel = relocate (orig); + + if ( orig != rel) + { + ds_clear (st); + ds_put_cstr (st, rel); + /* The documentation for relocate says that casting away const + and then freeing is appropriate ... */ + free (CONST_CAST (char *, rel)); + } +} + + + + +/* 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); + } +}