1 /*
2 * Copyright 2008-2014 Arsen Chaloyan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * $Id: apt_text_stream.h 2136 2014-07-04 06:33:36Z achaloyan@gmail.com $
17 */
18
19 #ifndef APT_TEXT_STREAM_H
20 #define APT_TEXT_STREAM_H
21
22 /**
23 * @file apt_text_stream.h
24 * @brief Text Stream Parse/Generate Routine
25 */
26
27 #include "apt_string_table.h"
28 #include "apt_pair.h"
29
30 APT_BEGIN_EXTERN_C
31
32 /** Space */
33 #define APT_TOKEN_SP 0x20
34 /** Horizontal tab */
35 #define APT_TOKEN_HTAB 0x09
36 /** Carrige return */
37 #define APT_TOKEN_CR 0x0D
38 /** Line feed */
39 #define APT_TOKEN_LF 0x0A
40
41 /** Text stream declaration */
42 typedef struct apt_text_stream_t apt_text_stream_t;
43
44 /** Text stream is used for message parsing and generation */
45 struct apt_text_stream_t {
46 /** Text stream */
47 apt_str_t text;
48
49 /** Current position in the stream */
50 char *pos;
51 /** End of stream pointer */
52 const char *end;
53 /** Is end of stream reached */
54 apt_bool_t is_eos;
55 };
56
57
58 /**
59 * Read entire line of the text stream.
60 * @param stream the text stream to navigate on
61 * @param line the read line to return
62 * @return TRUE if the line is successfully read, otherwise FALSE
63 * @remark To be used to navigate through the lines of the text stream (message).
64 */
65 APT_DECLARE(apt_bool_t) apt_text_line_read(apt_text_stream_t *stream, apt_str_t *line);
66
67 /**
68 * Read header field (name-value pair) of the text stream by scanning entire line.
69 * @param stream the text stream to navigate
70 * @param pair the read pair to return
71 * @return TRUE if the header is successfully read, otherwise FALSE
72 * @remark To be used to navigate through the lines and read header fields
73 * (name:value pairs) of the text stream (message).
74 */
75 APT_DECLARE(apt_bool_t) apt_text_header_read(apt_text_stream_t *stream, apt_pair_t *pair);
76
77 /**
78 * Read the field terminated with specified separator.
79 * @param stream the text stream to navigate
80 * @param separator the field separator
81 * @param skip_spaces whether to skip spaces or not
82 * @param field the read field to return
83 * @return TRUE if the read field isn't empty, otherwise FALSE
84 * @remark To be used to navigate through the fields of the text stream (message).
85 */
86 APT_DECLARE(apt_bool_t) apt_text_field_read(apt_text_stream_t *stream, char separator, apt_bool_t skip_spaces, apt_str_t *field);
87
88 /** Generate name-value pair line */
89 APT_DECLARE(apt_bool_t) apt_text_name_value_insert(apt_text_stream_t *stream, const apt_str_t *name, const apt_str_t *value);
90
91 /** Generate only the name ("name:") of the header field */
92 APT_DECLARE(apt_bool_t) apt_text_header_name_insert(apt_text_stream_t *stream, const apt_str_t *name);
93
94 /** Parse array of name-value pairs */
95 APT_DECLARE(apt_bool_t) apt_pair_array_parse(apt_pair_arr_t *arr, const apt_str_t *value, apr_pool_t *pool);
96 /** Generate array of name-value pairs */
97 APT_DECLARE(apt_bool_t) apt_pair_array_generate(const apt_pair_arr_t *arr, apt_str_t *str, apr_pool_t *pool);
98
99
100 /** Parse boolean-value */
101 APT_DECLARE(apt_bool_t) apt_boolean_value_parse(const apt_str_t *str, apt_bool_t *value);
102 /** Generate apr_size_t value from pool (buffer is allocated from pool) */
103 APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_str_t *str, apr_pool_t *pool);
104
105 /** Parse apr_size_t value */
106 APT_DECLARE(apr_size_t) apt_size_value_parse(const apt_str_t *str);
107 /** Generate apr_size_t value from pool (buffer is allocated from pool) */
108 APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_str_t *str, apr_pool_t *pool);
109
110 /** Insert apr_size_t value */
111 APT_DECLARE(apt_bool_t) apt_text_size_value_insert(apt_text_stream_t *stream, apr_size_t value);
112
113 /** Parse float value */
114 APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str);
115 /** Generate float value (buffer is allocated from pool) */
116 APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_str_t *str, apr_pool_t *pool);
117
118 /** Insert float value */
119 APT_DECLARE(apt_bool_t) apt_text_float_value_insert(apt_text_stream_t *stream, float value);
120 /** Insert string value */
121 APT_DECLARE(apt_bool_t) apt_text_string_insert(apt_text_stream_t *stream, const apt_str_t *str);
122
123 /** Reset navigation related data of the text stream */
apt_text_stream_reset(apt_text_stream_t * stream)124 static APR_INLINE void apt_text_stream_reset(apt_text_stream_t *stream)
125 {
126 stream->pos = stream->text.buf;
127 stream->end = stream->text.buf + stream->text.length;
128 stream->is_eos = FALSE;
129 }
130
131 /** Initialize text stream */
apt_text_stream_init(apt_text_stream_t * stream,char * buffer,apr_size_t size)132 static APR_INLINE void apt_text_stream_init(apt_text_stream_t *stream, char *buffer, apr_size_t size)
133 {
134 stream->text.buf = buffer;
135 stream->text.length = size;
136 apt_text_stream_reset(stream);
137 }
138
139 /** Insert end of the line symbol(s) */
apt_text_eol_insert(apt_text_stream_t * stream)140 static APR_INLINE apt_bool_t apt_text_eol_insert(apt_text_stream_t *stream)
141 {
142 if(stream->pos + 2 < stream->end) {
143 *stream->pos++ = APT_TOKEN_CR;
144 *stream->pos++ = APT_TOKEN_LF;
145 return TRUE;
146 }
147 return FALSE;
148 }
149
150 /** Insert character */
apt_text_char_insert(apt_text_stream_t * stream,char ch)151 static APR_INLINE apt_bool_t apt_text_char_insert(apt_text_stream_t *stream, char ch)
152 {
153 if(stream->pos + 1 < stream->end) {
154 *stream->pos++ = ch;
155 return TRUE;
156 }
157 return FALSE;
158 }
159
160 /** Insert space */
apt_text_space_insert(apt_text_stream_t * stream)161 static APR_INLINE apt_bool_t apt_text_space_insert(apt_text_stream_t *stream)
162 {
163 return apt_text_char_insert(stream,APT_TOKEN_SP);
164 }
165
166 /** Insert space */
apt_text_htab_insert(apt_text_stream_t * stream)167 static APR_INLINE apt_bool_t apt_text_htab_insert(apt_text_stream_t *stream)
168 {
169 return apt_text_char_insert(stream,APT_TOKEN_HTAB);
170 }
171
172 /** Check whether specified character is a white space (WSP = SP / HTAB) */
apt_text_is_wsp(char ch)173 static APR_INLINE apt_bool_t apt_text_is_wsp(char ch)
174 {
175 return (ch == APT_TOKEN_SP || ch == APT_TOKEN_HTAB) ? TRUE : FALSE;
176 }
177
178 /** Skip sequence of spaces */
apt_text_spaces_skip(apt_text_stream_t * stream)179 static APR_INLINE void apt_text_spaces_skip(apt_text_stream_t *stream)
180 {
181 while(stream->pos < stream->end && *stream->pos == APT_TOKEN_SP)
182 stream->pos++;
183 }
184
185 /** Skip sequence of white spaces (WSP = SP / HTAB) */
apt_text_white_spaces_skip(apt_text_stream_t * stream)186 static APR_INLINE void apt_text_white_spaces_skip(apt_text_stream_t *stream)
187 {
188 while(stream->pos < stream->end && apt_text_is_wsp(*stream->pos) == TRUE)
189 stream->pos++;
190 }
191
192 /** Skip specified character */
apt_text_char_skip(apt_text_stream_t * stream,char ch)193 static APR_INLINE void apt_text_char_skip(apt_text_stream_t *stream, char ch)
194 {
195 if(stream->pos < stream->end && *stream->pos == ch) stream->pos++;
196 }
197
198 /** Skip sequence of specified characters */
apt_text_chars_skip(apt_text_stream_t * stream,char ch)199 static APR_INLINE void apt_text_chars_skip(apt_text_stream_t *stream, char ch)
200 {
201 while(stream->pos < stream->end && *stream->pos == ch) stream->pos++;
202 }
203
204 /** Skip to specified character */
apt_text_skip_to_char(apt_text_stream_t * stream,char ch)205 static APR_INLINE void apt_text_skip_to_char(apt_text_stream_t *stream, char ch)
206 {
207 while(stream->pos < stream->end && *stream->pos != ch) stream->pos++;
208 }
209
210 /** Check whether end of stream is reached */
apt_text_is_eos(const apt_text_stream_t * stream)211 static APR_INLINE apt_bool_t apt_text_is_eos(const apt_text_stream_t *stream)
212 {
213 return (stream->pos >= stream->end || stream->is_eos == TRUE) ? TRUE : FALSE;
214 }
215
216 /** Scroll text stream */
217 APT_DECLARE(apt_bool_t) apt_text_stream_scroll(apt_text_stream_t *stream);
218
219 /** Parse id at resource string */
220 APT_DECLARE(apt_bool_t) apt_id_resource_parse(const apt_str_t *str, char separator, apt_str_t *id, apt_str_t *resource, apr_pool_t *pool);
221 /** Generate id at resource string */
222 APT_DECLARE(apt_bool_t) apt_id_resource_generate(const apt_str_t *id, const apt_str_t *resource, char separator, apt_str_t *str, apr_pool_t *pool);
223
224 /** Generate value plus the length (number of digits) of the value itself */
225 APT_DECLARE(apt_bool_t) apt_var_length_value_generate(apr_size_t *value, apr_size_t max_count, apt_str_t *str);
226
227 /** Generate completion-cause */
228 APT_DECLARE(apt_bool_t) apt_completion_cause_generate(const apt_str_table_item_t table[], apr_size_t size, apr_size_t cause, apt_str_t *str, apr_pool_t *pool);
229
230 /**
231 * Generate unique identifier (hex string)
232 * @param id the id to generate
233 * @param length the length of hex string to generate
234 * @param pool the pool to allocate memory from
235 */
236 APT_DECLARE(apt_bool_t) apt_unique_id_generate(apt_str_t *id, apr_size_t length, apr_pool_t *pool);
237
238
239 APT_END_EXTERN_C
240
241 #endif /* APT_TEXT_STREAM_H */
242