1#ifndef AWS_COMMON_STRING_H
2#define AWS_COMMON_STRING_H
3/*
4 * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License").
7 * You may not use this file except in compliance with the License.
8 * A copy of the License is located at
9 *
10 * http://aws.amazon.com/apache2.0
11 *
12 * or in the "license" file accompanying this file. This file is distributed
13 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14 * express or implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 */
17#include <aws/common/byte_buf.h>
18#include <aws/common/common.h>
19
20/**
21 * Represents an immutable string holding either text or binary data. If the
22 * string is in constant memory or memory that should otherwise not be freed by
23 * this struct, set allocator to NULL and destroy function will be a no-op.
24 *
25 * This is for use cases where the entire struct and the data bytes themselves
26 * need to be held in dynamic memory, such as when held by a struct
27 * aws_hash_table. The data bytes themselves are always held in contiguous
28 * memory immediately after the end of the struct aws_string, and the memory for
29 * both the header and the data bytes is allocated together.
30 *
31 * Use the aws_string_bytes function to access the data bytes. A null byte is
32 * always included immediately after the data but not counted in the length, so
33 * that the output of aws_string_bytes can be treated as a C-string in cases
34 * where none of the the data bytes are null.
35 *
36 * Note that the fields of this structure are const; this ensures not only that
37 * they cannot be modified, but also that you can't assign the structure using
38 * the = operator accidentally.
39 */
40
41/* Using a flexible array member is the C99 compliant way to have the bytes of
42 * the string immediately follow the header.
43 *
44 * MSVC doesn't know this for some reason so we need to use a pragma to make
45 * it happy.
46 */
47#ifdef _MSC_VER
48# pragma warning(push)
49# pragma warning(disable : 4200)
50#endif
51struct aws_string {
52 struct aws_allocator *const allocator;
53 const size_t len;
54 const uint8_t bytes[];
55};
56#ifdef _MSC_VER
57# pragma warning(pop)
58#endif
59
60AWS_EXTERN_C_BEGIN
61
62/**
63 * Returns true if bytes of string are the same, false otherwise.
64 */
65AWS_COMMON_API
66bool aws_string_eq(const struct aws_string *a, const struct aws_string *b);
67
68/**
69 * Returns true if bytes of string are equivalent, using a case-insensitive comparison.
70 */
71AWS_COMMON_API
72bool aws_string_eq_ignore_case(const struct aws_string *a, const struct aws_string *b);
73
74/**
75 * Returns true if bytes of string and cursor are the same, false otherwise.
76 */
77AWS_COMMON_API
78bool aws_string_eq_byte_cursor(const struct aws_string *str, const struct aws_byte_cursor *cur);
79
80/**
81 * Returns true if bytes of string and cursor are equivalent, using a case-insensitive comparison.
82 */
83AWS_COMMON_API
84bool aws_string_eq_byte_cursor_ignore_case(const struct aws_string *str, const struct aws_byte_cursor *cur);
85
86/**
87 * Returns true if bytes of string and buffer are the same, false otherwise.
88 */
89AWS_COMMON_API
90bool aws_string_eq_byte_buf(const struct aws_string *str, const struct aws_byte_buf *buf);
91
92/**
93 * Returns true if bytes of string and buffer are equivalent, using a case-insensitive comparison.
94 */
95AWS_COMMON_API
96bool aws_string_eq_byte_buf_ignore_case(const struct aws_string *str, const struct aws_byte_buf *buf);
97
98AWS_COMMON_API
99bool aws_string_eq_c_str(const struct aws_string *str, const char *c_str);
100
101/**
102 * Returns true if bytes of strings are equivalent, using a case-insensitive comparison.
103 */
104AWS_COMMON_API
105bool aws_string_eq_c_str_ignore_case(const struct aws_string *str, const char *c_str);
106
107/**
108 * Constructor functions which copy data from null-terminated C-string or array of bytes.
109 */
110AWS_COMMON_API
111struct aws_string *aws_string_new_from_c_str(struct aws_allocator *allocator, const char *c_str);
112AWS_COMMON_API
113struct aws_string *aws_string_new_from_array(struct aws_allocator *allocator, const uint8_t *bytes, size_t len);
114
115/**
116 * Allocate a new string with the same contents as the old.
117 */
118AWS_COMMON_API
119struct aws_string *aws_string_new_from_string(struct aws_allocator *allocator, const struct aws_string *str);
120
121/**
122 * Deallocate string.
123 */
124AWS_COMMON_API
125void aws_string_destroy(struct aws_string *str);
126
127/**
128 * Zeroes out the data bytes of string and then deallocates the memory.
129 * Not safe to run on a string created with AWS_STATIC_STRING_FROM_LITERAL.
130 */
131AWS_COMMON_API
132void aws_string_destroy_secure(struct aws_string *str);
133
134/**
135 * Compares lexicographical ordering of two strings. This is a binary
136 * byte-by-byte comparison, treating bytes as unsigned integers. It is suitable
137 * for either textual or binary data and is unaware of unicode or any other byte
138 * encoding. If both strings are identical in the bytes of the shorter string,
139 * then the longer string is lexicographically after the shorter.
140 *
141 * Returns a positive number if string a > string b. (i.e., string a is
142 * lexicographically after string b.) Returns zero if string a = string b.
143 * Returns negative number if string a < string b.
144 */
145AWS_COMMON_API
146int aws_string_compare(const struct aws_string *a, const struct aws_string *b);
147
148/**
149 * A convenience function for sorting lists of (const struct aws_string *) elements. This can be used as a
150 * comparator for aws_array_list_sort. It is just a simple wrapper around aws_string_compare.
151 */
152AWS_COMMON_API
153int aws_array_list_comparator_string(const void *a, const void *b);
154
155/**
156 * Defines a (static const struct aws_string *) with name specified in first
157 * argument that points to constant memory and has data bytes containing the
158 * string literal in the second argument.
159 *
160 * GCC allows direct initilization of structs with variable length final fields
161 * However, this might not be portable, so we can do this instead
162 * This will have to be updated whenever the aws_string structure changes
163 */
164#define AWS_STATIC_STRING_FROM_LITERAL(name, literal) \
165 static const struct { \
166 struct aws_allocator *const allocator; \
167 const size_t len; \
168 const uint8_t bytes[sizeof(literal)]; \
169 } name##_s = {NULL, sizeof(literal) - 1, literal}; \
170 static const struct aws_string *(name) = (struct aws_string *)(&name##_s)
171
172/*
173 * A related macro that declares the string pointer without static, allowing it to be externed as a global constant
174 */
175#define AWS_STRING_FROM_LITERAL(name, literal) \
176 static const struct { \
177 struct aws_allocator *const allocator; \
178 const size_t len; \
179 const uint8_t bytes[sizeof(literal)]; \
180 } name##_s = {NULL, sizeof(literal) - 1, literal}; \
181 const struct aws_string *(name) = (struct aws_string *)(&name##_s)
182
183/**
184 * Copies all bytes from string to buf.
185 *
186 * On success, returns true and updates the buf pointer/length
187 * accordingly. If there is insufficient space in the buf, returns
188 * false, leaving the buf unchanged.
189 */
190AWS_COMMON_API
191bool aws_byte_buf_write_from_whole_string(
192 struct aws_byte_buf *AWS_RESTRICT buf,
193 const struct aws_string *AWS_RESTRICT src);
194
195/**
196 * Creates an aws_byte_cursor from an existing string.
197 */
198AWS_COMMON_API
199struct aws_byte_cursor aws_byte_cursor_from_string(const struct aws_string *src);
200
201/**
202 * If the string was dynamically allocated, clones it. If the string was statically allocated (i.e. has no allocator),
203 * returns the original string.
204 */
205AWS_COMMON_API
206struct aws_string *aws_string_clone_or_reuse(struct aws_allocator *allocator, const struct aws_string *str);
207
208/* Computes the length of a c string in bytes assuming the character set is either ASCII or UTF-8. If no NULL character
209 * is found within max_read_len of str, AWS_ERROR_C_STRING_BUFFER_NOT_NULL_TERMINATED is raised. Otherwise, str_len
210 * will contain the string length minus the NULL character, and AWS_OP_SUCCESS will be returned. */
211AWS_COMMON_API
212int aws_secure_strlen(const char *str, size_t max_read_len, size_t *str_len);
213
214/**
215 * Equivalent to str->bytes.
216 */
217AWS_STATIC_IMPL
218const uint8_t *aws_string_bytes(const struct aws_string *str);
219
220/**
221 * Equivalent to `(const char *)str->bytes`.
222 */
223AWS_STATIC_IMPL
224const char *aws_string_c_str(const struct aws_string *str);
225
226/**
227 * Evaluates the set of properties that define the shape of all valid aws_string structures.
228 * It is also a cheap check, in the sense it run in constant time (i.e., no loops or recursion).
229 */
230AWS_STATIC_IMPL
231bool aws_string_is_valid(const struct aws_string *str);
232
233/**
234 * Best-effort checks aws_string invariants, when the str->len is unknown
235 */
236AWS_STATIC_IMPL
237bool aws_c_string_is_valid(const char *str);
238
239#ifndef AWS_NO_STATIC_IMPL
240# include <aws/common/string.inl>
241#endif /* AWS_NO_STATIC_IMPL */
242
243AWS_EXTERN_C_END
244
245#endif /* AWS_COMMON_STRING_H */
246