X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flibpspp%2Fstr.c;h=ca23b08b7290c93ddc8138ff5810dbc0f9317f0f;hb=9683d7528884fcb3c60705812de9f96889536388;hp=67d189dda91239bd536dab224fc607d7c7c20ab9;hpb=b74d09af5e07f954c18e7cdb8aca3af47fa10208;p=pspp-builds.git diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 67d189dd..ca23b08b 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. - Written by Ben Pfaff . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -27,6 +26,7 @@ #include #include +#include #include "minmax.h" #include "size_max.h" @@ -157,6 +157,22 @@ buf_copy_str_lpad (char *dst, size_t dst_size, const char *src) } } +/* 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. */ +void +buf_copy_lpad (char *dst, size_t dst_size, + const char *src, size_t src_size) +{ + if (src_size >= dst_size) + memmove (dst, src, dst_size); + else + { + memset (dst, ' ', 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. */ @@ -252,6 +268,15 @@ spprintf (char *dst, const char *format, ...) return dst + count; } + +/* Sets the SIZE bytes starting at BLOCK to C, + and returns the byte following BLOCK. */ +void * +mempset (void *block, int c, size_t size) +{ + memset (block, c, size); + return (char *) block + size; +} /* Substrings. */ @@ -332,6 +357,25 @@ ss_alloc_uninit (struct substring *new, size_t cnt) new->length = cnt; } +/* Makes a pool_alloc_unaligned()'d 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->length = old.length; + memcpy (new->string, old.string, old.length); +} + +/* Allocates room for a CNT-character string in NEW in POOL. */ +void +ss_alloc_uninit_pool (struct substring *new, size_t cnt, struct pool *pool) +{ + new->string = pool_alloc_unaligned (pool, cnt); + new->length = cnt; +} + /* Frees the string that SS points to. */ void ss_dealloc (struct substring *ss) @@ -427,7 +471,8 @@ ss_separate (struct substring ss, struct substring delimiters, /* Divides SS into tokens separated by any of the DELIMITERS, merging adjacent delimiters so that the empty string is never produced as a token. Each call replaces TOKEN by the next - token in SS, or by an empty string if no tokens remain. + token in SS, or by an empty string if no tokens remain, and + then skips past the first delimiter following the token. Returns true if a token was obtained, false otherwise. Before the first call, initialize *SAVE_IDX to 0. Do not @@ -438,7 +483,8 @@ ss_tokenize (struct substring ss, struct substring delimiters, { ss_advance (&ss, *save_idx); *save_idx += ss_ltrim (&ss, delimiters); - *save_idx += ss_get_chars (&ss, ss_cspan (ss, delimiters), token); + ss_get_chars (&ss, ss_cspan (ss, delimiters), token); + *save_idx += ss_length (*token) + 1; return ss_length (*token) > 0; } @@ -467,6 +513,21 @@ ss_match_char (struct substring *ss, char c) return false; } +/* If SS begins with TARGET, removes it and returns true. + Otherwise, returns false without changing SS. */ +bool +ss_match_string (struct substring *ss, const struct substring target) +{ + size_t length = ss_length (target); + if (ss_equals (ss_head (*ss, length), target)) + { + ss_advance (ss, length); + return true; + } + else + return false; +} + /* Removes the first character from SS and returns it. If SS is empty, returns EOF without modifying SS. */ int @@ -494,7 +555,7 @@ ss_get_until (struct substring *ss, char delimiter, struct substring *out) /* Stores the first CNT characters in SS in OUT (or fewer, if SS is shorter than CNT characters). Trims the same characters - from the beginning of SS. */ + from the beginning of SS. Returns CNT. */ size_t ss_get_chars (struct substring *ss, size_t cnt, struct substring *out) { @@ -503,6 +564,36 @@ ss_get_chars (struct substring *ss, size_t cnt, struct substring *out) return cnt; } +/* Parses and removes an optionally signed decimal integer from + the beginning of SS. Returns 0 if an error occurred, + otherwise the number of characters removed from SS. Stores + the integer's value into *VALUE. */ +size_t +ss_get_long (struct substring *ss, long *value) +{ + char tmp[64]; + size_t length; + + length = ss_span (*ss, ss_cstr ("+-")); + length += ss_span (ss_substr (*ss, length, SIZE_MAX), ss_cstr (CC_DIGITS)); + if (length > 0 && length < sizeof tmp) + { + char *tail; + + memcpy (tmp, ss_data (*ss), length); + tmp[length] = '\0'; + + *value = strtol (tmp, &tail, 10); + if (tail - tmp == length) + { + ss_advance (ss, length); + return length; + } + } + *value = 0; + return 0; +} + /* Returns true if SS is empty (contains no characters), false otherwise. */ bool @@ -601,6 +692,34 @@ ss_compare (struct substring a, struct substring b) return retval; } +/* Compares A and B case-insensitively and returns a + strcmp()-type comparison result. */ +int +ss_compare_case (struct substring a, struct substring b) +{ + int retval = memcasecmp (a.string, b.string, MIN (a.length, b.length)); + if (retval == 0) + retval = a.length < b.length ? -1 : a.length > b.length; + return retval; +} + +/* Compares A and B and returns true if their contents are + identical, false otherwise. */ +int +ss_equals (struct substring a, struct substring b) +{ + return a.length == b.length && !memcmp (a.string, b.string, a.length); +} + +/* Compares A and B and returns true if their contents are + identical except possibly for case differences, false + otherwise. */ +int +ss_equals_case (struct substring a, struct substring b) +{ + return a.length == b.length && !memcasecmp (a.string, b.string, a.length); +} + /* Returns the position in SS that the character at P occupies. P must point within SS or one past its end. */ size_t @@ -676,6 +795,30 @@ ds_swap (struct string *a, struct string *b) *b = tmp; } +/* Helper function for ds_register_pool. */ +static void +free_string (void *st_) +{ + struct string *st = st_; + ds_destroy (st); +} + +/* Arranges for ST to be destroyed automatically as part of + POOL. */ +void +ds_register_pool (struct string *st, struct pool *pool) +{ + pool_register (pool, free_string, st); +} + +/* Cancels the arrangement for ST to be destroyed automatically + as part of POOL. */ +void +ds_unregister_pool (struct string *st, struct pool *pool) +{ + pool_unregister (pool, st); +} + /* Copies SRC into DST. DST and SRC may be the same string. */ void @@ -860,6 +1003,18 @@ ds_rpad (struct string *st, size_t length, char pad) ds_put_char_multiple (st, pad, length - st->ss.length); } +/* Sets the length of ST to exactly NEW_LENGTH, + either by truncating characters from the end, + or by padding on the right with PAD. */ +void +ds_set_length (struct string *st, size_t new_length, char pad) +{ + if (st->ss.length < new_length) + ds_rpad (st, new_length, pad); + else + st->ss.length = new_length; +} + /* Returns true if ST is empty, false otherwise. */ bool ds_is_empty (const struct string *st)