1 /*
2  * Copyright (c) 2014,2015 DeNA Co., Ltd., Kazuho Oku, Justin Zhu
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef h2o__string_h
23 #define h2o__string_h
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #include <stddef.h>
30 #include <stdint.h>
31 #include <time.h>
32 #include "h2o/memory.h"
33 
34 #define H2O_STRLIT(s) (s), sizeof(s) - 1
35 
36 #define H2O_INT16_LONGEST_STR "-32768"
37 #define H2O_UINT16_LONGEST_STR "65535"
38 #define H2O_INT32_LONGEST_STR "-2147483648"
39 #define H2O_UINT32_LONGEST_STR "4294967295"
40 #define H2O_INT64_LONGEST_STR "-9223372036854775808"
41 #define H2O_UINT64_LONGEST_STR "18446744073709551615"
42 #define H2O_UINT64_LONGEST_HEX_STR "FFFFFFFFFFFFFFFF"
43 
44 #define H2O_SIZE_T_LONGEST_STR                                                                                                     \
45     H2O_UINT64_LONGEST_STR /* As it is hard to define a macro based on the actual size of size_t, we hard-code it to 64-bits and   \
46                               assert that in string.c */
47 
48 /**
49  * duplicates given string
50  * @param pool memory pool (or NULL to use malloc)
51  * @param s source string
52  * @param len length of the source string (the result of strlen(s) used in case len is SIZE_MAX)
53  * @return buffer pointing to the duplicated string (buf is NUL-terminated but the length does not include the NUL char)
54  */
55 h2o_iovec_t h2o_strdup(h2o_mem_pool_t *pool, const char *s, size_t len);
56 /**
57  * variant of h2o_strdup that calls h2o_mem_alloc_shared
58  */
59 h2o_iovec_t h2o_strdup_shared(h2o_mem_pool_t *pool, const char *s, size_t len);
60 /**
61  * duplicates given string appending '/' to the tail if not found
62  */
63 h2o_iovec_t h2o_strdup_slashed(h2o_mem_pool_t *pool, const char *s, size_t len);
64 /**
65  * tr/A-Z/a-z/
66  */
67 static int h2o_tolower(int ch);
68 /**
69  * tr/A-Z/a-z/
70  */
71 static void h2o_strtolower(char *s, size_t len);
72 /**
73  * copies and converts the string to lower-case
74  */
75 static void h2o_strcopytolower(char *d, const char *s, size_t len);
76 /**
77  * tr/a-z/A-Z/
78  */
79 static int h2o_toupper(int ch);
80 /**
81  * tr/a-z/A-Z/
82  */
83 static void h2o_strtoupper(char *s, size_t len);
84 /**
85  * tests if target string (target_len bytes long) is equal to test string (test_len bytes long) after being converted to lower-case
86  */
87 static int h2o_lcstris(const char *target, size_t target_len, const char *test, size_t test_len);
88 /**
89  * turns the length of a string into the length of the same string encoded in base64
90  */
91 static size_t h2o_base64_encode_capacity(size_t len);
92 /**
93  * parses a positive number of return SIZE_MAX if failed
94  */
95 size_t h2o_strtosize(const char *s, size_t len);
96 /**
97  * parses first positive number contained in *s or return SIZE_MAX if failed.
98  * *s will set to right after the number in string or right after the end of string.
99  */
100 size_t h2o_strtosizefwd(char **s, size_t len);
101 /**
102  * base64 url decoder
103  */
104 h2o_iovec_t h2o_decode_base64url(h2o_mem_pool_t *pool, const char *src, size_t len);
105 /**
106  * base64 encoder (note: the function emits trailing '\0')
107  */
108 size_t h2o_base64_encode(char *dst, const void *src, size_t len, int url_encoded);
109 /**
110  * decodes hexadecimal string
111  */
112 int h2o_hex_decode(void *dst, const char *src, size_t src_len);
113 /**
114  * encodes binary into a hexadecimal string (with '\0' appended at last)
115  */
116 void h2o_hex_encode(char *dst, const void *src, size_t src_len);
117 /**
118  * URI-ecsapes given string (as defined in RFC 3986)
119  */
120 h2o_iovec_t h2o_uri_escape(h2o_mem_pool_t *pool, const char *s, size_t l, const char *preserve_chars);
121 /**
122  * returns the extension portion of path
123  */
124 h2o_iovec_t h2o_get_filext(const char *path, size_t len);
125 /**
126  * returns a vector with surrounding WS stripped
127  */
128 h2o_iovec_t h2o_str_stripws(const char *s, size_t len);
129 /**
130  * returns the offset of given substring or SIZE_MAX if not found
131  */
132 size_t h2o_strstr(const char *haysack, size_t haysack_len, const char *needle, size_t needle_len);
133 /**
134  * Parses a string into tokens or name-value pairs. Each token is returned as a tuple of (returned_pointer, *element_len). When the
135  * input is fully consumed, NULL is returned. See t/00unit/lib/common/string.c for examples.
136  *
137  * @param iter   Iterator. When calling the function for the first time, this vector should point to the entire string to be parsed.
138  * @param inner  Separator to separate tokens.
139  * @param outer  The outer separator. When parsing a flat list, the values of `inner` and `outer` should be identical. When parsing
140  *               a nested list, this value specifies the outer separator.  For example, (inner, outer) would be set to (';', ',')
141  *               when parsing a Cache-Control header field value. In such case, boundary of sublists is signaled to the caller by
142  *               returning a token pointing to the outer separator.
143  * @param value  [optional] When a non-NULL address is given and if the found element contains `=`, that element is split into a
144  *               name-value pair and the range of the value is returned using this parameter. The name is returned as the token.
145  */
146 const char *h2o_next_token(h2o_iovec_t *iter, int inner, int outer, size_t *element_len, h2o_iovec_t *value);
147 /**
148  * tests if string needle exists within a separator-separated string (for handling "#rule" of RFC 2616)
149  */
150 int h2o_contains_token(const char *haysack, size_t haysack_len, const char *needle, size_t needle_len, int separator);
151 /**
152  * HTML-escapes a string
153  * @param pool memory pool
154  * @param src source string
155  * @param len source length
156  * @return the escaped string, or the source itself if escape was not necessary
157  */
158 h2o_iovec_t h2o_htmlescape(h2o_mem_pool_t *pool, const char *src, size_t len);
159 /**
160  * concatenates a list of iovecs (with NUL termination)
161  */
162 #define h2o_concat(pool, ...)                                                                                                      \
163     h2o_concat_list(pool, (h2o_iovec_t[]){__VA_ARGS__}, sizeof((h2o_iovec_t[]){__VA_ARGS__}) / sizeof(h2o_iovec_t))
164 h2o_iovec_t h2o_concat_list(h2o_mem_pool_t *pool, h2o_iovec_t *list, size_t count);
165 /**
166  * joins the separated strings of iovecs into a single iovec
167  */
168 h2o_iovec_t h2o_join_list(h2o_mem_pool_t *pool, h2o_iovec_t *list, size_t count, h2o_iovec_t delimiter);
169 /**
170  * splits the string str into a list of iovec
171  */
172 void h2o_split(h2o_mem_pool_t *pool, h2o_iovec_vector_t *list, h2o_iovec_t str, const char needle);
173 /**
174  * emits a two-line string to buf that graphically points to given location within the source string
175  * @return 0 if successful
176  */
177 int h2o_str_at_position(char *buf, const char *src, size_t src_len, int lineno, int column);
178 
179 int h2o__lcstris_core(const char *target, const char *test, size_t test_len);
180 
181 /**
182  * Encode a Structured Field Value [RFC 8941] of type String ("sf-string" in the RFC)
183  * @param pool memory pool (or NULL to use malloc)
184  * @param s source string
185  * @param slen length of source string; if slen==SIZE_MAX, then strlen(s) will be used
186  * @return buffer pointing to the encoded string (buf is NUL-terminated but the length does not include the NUL char)
187  */
188 h2o_iovec_t h2o_encode_sf_string(h2o_mem_pool_t *pool, const char *s, size_t slen);
189 
190 /* inline defs */
191 
h2o_tolower(int ch)192 inline int h2o_tolower(int ch)
193 {
194     return 'A' <= ch && ch <= 'Z' ? ch + 0x20 : ch;
195 }
196 
h2o_strtolower(char * s,size_t len)197 inline void h2o_strtolower(char *s, size_t len)
198 {
199     h2o_strcopytolower(s, s, len);
200 }
201 
h2o_strcopytolower(char * d,const char * s,size_t len)202 inline void h2o_strcopytolower(char *d, const char *s, size_t len)
203 {
204     for (; len != 0; ++d, ++s, --len)
205         *d = h2o_tolower(*s);
206 }
207 
h2o_toupper(int ch)208 inline int h2o_toupper(int ch)
209 {
210     return 'a' <= ch && ch <= 'z' ? ch - 0x20 : ch;
211 }
212 
h2o_strtoupper(char * s,size_t len)213 inline void h2o_strtoupper(char *s, size_t len)
214 {
215     for (; len != 0; ++s, --len)
216         *s = h2o_toupper(*s);
217 }
218 
h2o_lcstris(const char * target,size_t target_len,const char * test,size_t test_len)219 inline int h2o_lcstris(const char *target, size_t target_len, const char *test, size_t test_len)
220 {
221     if (target_len != test_len)
222         return 0;
223     return h2o__lcstris_core(target, test, test_len);
224 }
225 
h2o_base64_encode_capacity(size_t len)226 inline size_t h2o_base64_encode_capacity(size_t len)
227 {
228     return (((len) + 2) / 3 * 4 + 1);
229 }
230 
231 #ifdef __cplusplus
232 }
233 #endif
234 
235 #endif
236