1 /* String descriptors.
2 Copyright (C) 2023 Free Software Foundation, Inc.
3
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
8
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2023. */
18
19 #ifndef _STRING_DESC_H
20 #define _STRING_DESC_H 1
21
22 /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE,
23 _GL_ATTRIBUTE_NODISCARD. */
24 #if !_GL_CONFIG_H_INCLUDED
25 #error "Please include config.h first."
26 #endif
27
28 /* Get ptrdiff_t. */
29 #include <stddef.h>
30
31 /* Get FILE. */
32 #include <stdio.h>
33
34 /* Get abort(), free(). */
35 #include <stdlib.h>
36
37 /* Get idx_t. */
38 #include "idx.h"
39
40
41 _GL_INLINE_HEADER_BEGIN
42 #ifndef GL_STRING_DESC_INLINE
43 # define GL_STRING_DESC_INLINE _GL_INLINE
44 #endif
45
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49
50
51 /* Type describing a string that may contain NUL bytes.
52 It's merely a descriptor of an array of bytes. */
53 typedef struct string_desc_t string_desc_t;
54 struct string_desc_t
55 {
56 /* The fields of this struct should be considered private. */
57 idx_t _nbytes;
58 char *_data;
59 };
60
61 /* String descriptors can be passed and returned by value.
62
63 String descriptors and NUL-terminated 'const char *'/'char *' C strings
64 cannot be used interchangeably. You will get compilation errors if you
65 attempt to assign a string descriptor to a C string or vice versa. */
66
67
68 /* ==== Side-effect-free operations on string descriptors ==== */
69
70 /* Return the length of the string S. */
71 #if 0 /* Defined inline below. */
72 extern idx_t string_desc_length (string_desc_t s);
73 #endif
74
75 /* Return the byte at index I of string S.
76 I must be < length(S). */
77 #if 0 /* Defined inline below. */
78 extern char string_desc_char_at (string_desc_t s, idx_t i);
79 #endif
80
81 /* Return a read-only view of the bytes of S. */
82 #if 0 /* Defined inline below. */
83 extern const char * string_desc_data (string_desc_t s);
84 #endif
85
86 /* Return true if S is the empty string. */
87 #if 0 /* Defined inline below. */
88 extern bool string_desc_is_empty (string_desc_t s);
89 #endif
90
91 /* Return true if A and B are equal. */
92 extern bool string_desc_equals (string_desc_t a, string_desc_t b);
93
94 /* Return true if S starts with PREFIX. */
95 extern bool string_desc_startswith (string_desc_t s, string_desc_t prefix);
96
97 /* Return true if S ends with SUFFIX. */
98 extern bool string_desc_endswith (string_desc_t s, string_desc_t suffix);
99
100 /* Return > 0, == 0, or < 0 if A > B, A == B, A < B.
101 This uses a lexicographic ordering, where the bytes are compared as
102 'unsigned char'. */
103 extern int string_desc_cmp (string_desc_t a, string_desc_t b);
104
105 /* Return the index of the first occurrence of C in S,
106 or -1 if there is none. */
107 extern ptrdiff_t string_desc_index (string_desc_t s, char c);
108
109 /* Return the index of the last occurrence of C in S,
110 or -1 if there is none. */
111 extern ptrdiff_t string_desc_last_index (string_desc_t s, char c);
112
113 /* Return the index of the first occurrence of NEEDLE in HAYSTACK,
114 or -1 if there is none. */
115 extern ptrdiff_t string_desc_contains (string_desc_t haystack, string_desc_t needle);
116
117 /* Return an empty string. */
118 extern string_desc_t string_desc_new_empty (void);
119
120 /* Return a string that represents the C string S, of length strlen (S). */
121 extern string_desc_t string_desc_from_c (const char *s);
122
123 /* Return the substring of S, starting at offset START and ending at offset END.
124 START must be <= END.
125 The result is of length END - START.
126 The result must not be freed (since its storage is part of the storage
127 of S). */
128 extern string_desc_t string_desc_substring (string_desc_t s, idx_t start, idx_t end);
129
130 /* Output S to the file descriptor FD.
131 Return 0 if successful.
132 Upon error, return -1 with errno set. */
133 extern int string_desc_write (int fd, string_desc_t s);
134
135 /* Output S to the FILE stream FP.
136 Return 0 if successful.
137 Upon error, return -1. */
138 extern int string_desc_fwrite (FILE *fp, string_desc_t s);
139
140
141 /* ==== Memory-allocating operations on string descriptors ==== */
142
143 /* Construct a string of length N, with uninitialized contents.
144 Return 0 if successful.
145 Upon error, return -1 with errno set. */
146 _GL_ATTRIBUTE_NODISCARD
147 extern int string_desc_new (string_desc_t *resultp, idx_t n);
148
149 /* Construct and return a string of length N, at the given memory address. */
150 extern string_desc_t string_desc_new_addr (idx_t n, char *addr);
151
152 /* Construct a string of length N, filled with C.
153 Return 0 if successful.
154 Upon error, return -1 with errno set. */
155 _GL_ATTRIBUTE_NODISCARD
156 extern int string_desc_new_filled (string_desc_t *resultp, idx_t n, char c);
157
158 /* Construct a copy of string S.
159 Return 0 if successful.
160 Upon error, return -1 with errno set. */
161 _GL_ATTRIBUTE_NODISCARD
162 extern int string_desc_copy (string_desc_t *resultp, string_desc_t s);
163
164 /* Construct the concatenation of N strings. N must be > 0.
165 Return 0 if successful.
166 Upon error, return -1 with errno set. */
167 _GL_ATTRIBUTE_NODISCARD
168 extern int string_desc_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...);
169
170 /* Construct a copy of string S, as a NUL-terminated C string.
171 Return it is successful.
172 Upon error, return NULL with errno set. */
173 extern char * string_desc_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE;
174
175
176 /* ==== Operations with side effects on string descriptors ==== */
177
178 /* Overwrite the byte at index I of string S with C.
179 I must be < length(S). */
180 extern void string_desc_set_char_at (string_desc_t s, idx_t i, char c);
181
182 /* Fill part of S, starting at offset START and ending at offset END,
183 with copies of C.
184 START must be <= END. */
185 extern void string_desc_fill (string_desc_t s, idx_t start, idx_t end, char c);
186
187 /* Overwrite part of S with T, starting at offset START.
188 START + length(T) must be <= length (S). */
189 extern void string_desc_overwrite (string_desc_t s, idx_t start, string_desc_t t);
190
191 /* Free S. */
192 extern void string_desc_free (string_desc_t s);
193
194
195 /* ==== Inline function definitions ==== */
196
197 GL_STRING_DESC_INLINE idx_t
198 string_desc_length (string_desc_t s)
199 {
200 return s._nbytes;
201 }
202
203 GL_STRING_DESC_INLINE char
204 string_desc_char_at (string_desc_t s, idx_t i)
205 {
206 if (!(i >= 0 && i < s._nbytes))
207 /* Invalid argument. */
208 abort ();
209 return s._data[i];
210 }
211
212 GL_STRING_DESC_INLINE const char *
213 string_desc_data (string_desc_t s)
214 {
215 return s._data;
216 }
217
218 GL_STRING_DESC_INLINE bool
219 string_desc_is_empty (string_desc_t s)
220 {
221 return s._nbytes == 0;
222 }
223
224
225 #ifdef __cplusplus
226 }
227 #endif
228
229 _GL_INLINE_HEADER_END
230
231
232 #endif /* _STRING_DESC_H */