/* String descriptors. Copyright (C) 2023-2024 Free Software Foundation, Inc. This file is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* Written by Bruno Haible , 2023. */ #ifndef _STRING_DESC_H #define _STRING_DESC_H 1 /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, _GL_ATTRIBUTE_NODISCARD. */ #if !_GL_CONFIG_H_INCLUDED #error "Please include config.h first." #endif /* Get ptrdiff_t. */ #include /* Get FILE. */ #include /* Get abort(), free(). */ #include /* Get idx_t. */ #include "idx.h" _GL_INLINE_HEADER_BEGIN #ifndef GL_STRING_DESC_INLINE # define GL_STRING_DESC_INLINE _GL_INLINE #endif #ifdef __cplusplus extern "C" { #endif /* Type describing a string that may contain NUL bytes. It's merely a descriptor of an array of bytes. */ typedef struct string_desc_t string_desc_t; struct string_desc_t { /* The fields of this struct should be considered private. */ idx_t _nbytes; char *_data; }; /* String descriptors can be passed and returned by value. String descriptors and NUL-terminated 'const char *'/'char *' C strings cannot be used interchangeably. You will get compilation errors if you attempt to assign a string descriptor to a C string or vice versa. */ /* ==== Side-effect-free operations on string descriptors ==== */ /* Return the length of the string S. */ #if 0 /* Defined inline below. */ extern idx_t string_desc_length (string_desc_t s); #endif /* Return the byte at index I of string S. I must be < length(S). */ #if 0 /* Defined inline below. */ extern char string_desc_char_at (string_desc_t s, idx_t i); #endif /* Return a read-only view of the bytes of S. */ #if 0 /* Defined inline below. */ extern const char * string_desc_data (string_desc_t s); #endif /* Return true if S is the empty string. */ #if 0 /* Defined inline below. */ extern bool string_desc_is_empty (string_desc_t s); #endif /* Return true if A and B are equal. */ extern bool string_desc_equals (string_desc_t a, string_desc_t b); /* Return true if S starts with PREFIX. */ extern bool string_desc_startswith (string_desc_t s, string_desc_t prefix); /* Return true if S ends with SUFFIX. */ extern bool string_desc_endswith (string_desc_t s, string_desc_t suffix); /* Return > 0, == 0, or < 0 if A > B, A == B, A < B. This uses a lexicographic ordering, where the bytes are compared as 'unsigned char'. */ extern int string_desc_cmp (string_desc_t a, string_desc_t b); /* Return the index of the first occurrence of C in S, or -1 if there is none. */ extern ptrdiff_t string_desc_index (string_desc_t s, char c); /* Return the index of the last occurrence of C in S, or -1 if there is none. */ extern ptrdiff_t string_desc_last_index (string_desc_t s, char c); /* Return the index of the first occurrence of NEEDLE in HAYSTACK, or -1 if there is none. */ extern ptrdiff_t string_desc_contains (string_desc_t haystack, string_desc_t needle); /* Return an empty string. */ extern string_desc_t string_desc_new_empty (void); /* Return a string that represents the C string S, of length strlen (S). */ extern string_desc_t string_desc_from_c (const char *s); /* Return the substring of S, starting at offset START and ending at offset END. START must be <= END. The result is of length END - START. The result must not be freed (since its storage is part of the storage of S). */ extern string_desc_t string_desc_substring (string_desc_t s, idx_t start, idx_t end); /* Output S to the file descriptor FD. Return 0 if successful. Upon error, return -1 with errno set. */ extern int string_desc_write (int fd, string_desc_t s); /* Output S to the FILE stream FP. Return 0 if successful. Upon error, return -1. */ extern int string_desc_fwrite (FILE *fp, string_desc_t s); /* ==== Memory-allocating operations on string descriptors ==== */ /* Construct a string of length N, with uninitialized contents. Return 0 if successful. Upon error, return -1 with errno set. */ _GL_ATTRIBUTE_NODISCARD extern int string_desc_new (string_desc_t *resultp, idx_t n); /* Construct and return a string of length N, at the given memory address. */ extern string_desc_t string_desc_new_addr (idx_t n, char *addr); /* Construct a string of length N, filled with C. Return 0 if successful. Upon error, return -1 with errno set. */ _GL_ATTRIBUTE_NODISCARD extern int string_desc_new_filled (string_desc_t *resultp, idx_t n, char c); /* Construct a copy of string S. Return 0 if successful. Upon error, return -1 with errno set. */ _GL_ATTRIBUTE_NODISCARD extern int string_desc_copy (string_desc_t *resultp, string_desc_t s); /* Construct the concatenation of N strings. N must be > 0. Return 0 if successful. Upon error, return -1 with errno set. */ _GL_ATTRIBUTE_NODISCARD extern int string_desc_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...); /* Construct a copy of string S, as a NUL-terminated C string. Return it is successful. Upon error, return NULL with errno set. */ extern char * string_desc_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE; /* ==== Operations with side effects on string descriptors ==== */ /* Overwrite the byte at index I of string S with C. I must be < length(S). */ extern void string_desc_set_char_at (string_desc_t s, idx_t i, char c); /* Fill part of S, starting at offset START and ending at offset END, with copies of C. START must be <= END. */ extern void string_desc_fill (string_desc_t s, idx_t start, idx_t end, char c); /* Overwrite part of S with T, starting at offset START. START + length(T) must be <= length (S). */ extern void string_desc_overwrite (string_desc_t s, idx_t start, string_desc_t t); /* Free S. */ extern void string_desc_free (string_desc_t s); /* ==== Inline function definitions ==== */ GL_STRING_DESC_INLINE idx_t string_desc_length (string_desc_t s) { return s._nbytes; } GL_STRING_DESC_INLINE char string_desc_char_at (string_desc_t s, idx_t i) { if (!(i >= 0 && i < s._nbytes)) /* Invalid argument. */ abort (); return s._data[i]; } GL_STRING_DESC_INLINE const char * string_desc_data (string_desc_t s) { return s._data; } GL_STRING_DESC_INLINE bool string_desc_is_empty (string_desc_t s) { return s._nbytes == 0; } #ifdef __cplusplus } #endif _GL_INLINE_HEADER_END #endif /* _STRING_DESC_H */