Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_command_local_parse.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Parse functions to support afw command local server
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 
10 #include "afw.h"
11 #include "afw_command_internal.h"
13 
26 static void
27 impl_get_token(afw_command_local_parse_t *x)
28 {
29  const afw_byte_t *start;
30 
31  for (;;) {
32  if (x->cursor >= x->end) {
33  x->token_type = afw_command_local_parse_token_type_end_of_input;
34  return;
35  }
36  if (*x->cursor != ' ') {
37  break;
38  }
39  x->cursor++;
40  }
41 
42  if (*x->cursor == '\r') {
43  x->token_type = afw_command_local_parse_token_type_end_of_line;
44  x->cursor++;
45  if (x->cursor >= x->end) {
46  return;
47  }
48  if (*x->cursor == '\n') {
49  x->cursor++;
50  return;
51  }
52  }
53 
54  if (*x->cursor == '\n') {
55  x->token_type = afw_command_local_parse_token_type_end_of_line;
56  x->cursor++;
57  return;
58  }
59 
60  if (*x->cursor == ':') {
61  x->token_type = afw_command_local_parse_token_type_colon;
62  x->cursor++;
63  return;
64  }
65 
66  if (*x->cursor == '"') {
67  x->cursor++;
68  start = x->cursor;
69 
70  for (;; x->cursor++) {
71  if (x->cursor >= x->end) {
72  x->token_type = afw_command_local_parse_token_type_invalid;
73  return;
74  }
75  if (*x->cursor == '"') {
77  x->token_type = afw_command_local_parse_token_type_string;
78  x->string = afw_utf8_create_copy(
79  (const afw_utf8_octet_t *)start,
80  (x->cursor - start),
81  x->p, x->xctx);
82  x->cursor++;
83  return;
84  }
85  }
86  }
87 
88  for (start = x->cursor; ; x->cursor++) {
89  if (x->cursor >= x->end) {
90  x->token_type = afw_command_local_parse_token_type_invalid;
91  return;
92  }
93  if (*x->cursor == ' ' ||
94  *x->cursor == '\n' ||
95  *x->cursor == '\r' ||
96  *x->cursor == ':')
97  {
98  x->token_type = afw_command_local_parse_token_type_string;
99  x->string = afw_utf8_create_copy(
100  (const afw_utf8_octet_t *)start,
101  (x->cursor - start),
102  x->p, x->xctx);
103  return;
104  }
105  }
106 }
107 
108 
109 /* This is a very minimal parser and should only be used for http-like. */
111 afw_command_local_parse_request(
113  const afw_memory_t **input,
114  afw_xctx_t *xctx)
115 {
116  const afw_utf8_t *name;
117  afw_memory_t *payload;
119 
120  afw_memory_clear(&x);
121  x.xctx = xctx;
122  x.p = xctx->p;
123  x.input = *input;
124  x.cursor = x.input->ptr;
125  x.end = (*input)->ptr + (*input)->size;
126  x.line_number = 1;
127 
128  /* METHOD */
129  impl_get_token(&x);
130  if (x.token_type != afw_command_local_parse_token_type_string) {
131  AFW_THROW_ERROR_FZ(general, xctx,
132  "Line %" AFW_SIZE_T_FMT ": Expecting METHOD",
133  x.line_number);
134  }
135  afw_object_set_property_as_string(self->this_request_properties,
136  &afw_s_REQUEST_METHOD, x.string, xctx);
137 
138  /* URI */
139  impl_get_token(&x);
140  if (x.token_type != afw_command_local_parse_token_type_string) {
141  AFW_THROW_ERROR_FZ(general, xctx,
142  "Line %" AFW_SIZE_T_FMT ": Expecting URI",
143  x.line_number);
144  }
145  afw_object_set_property_as_string(self->this_request_properties,
146  &afw_s_REQUEST_URI, x.string, xctx);
147 
148  /* SERVER_PROTOCOL */
149  impl_get_token(&x);
150  if (x.token_type != afw_command_local_parse_token_type_string) {
151  AFW_THROW_ERROR_FZ(general, xctx,
152  "Line %" AFW_SIZE_T_FMT ": Expecting URI",
153  x.line_number);
154  }
155  afw_object_set_property_as_string(self->this_request_properties,
156  &afw_command_s_SERVER_PROTOCOL, x.string, xctx);
157 
158  /* End of line */
159  impl_get_token(&x);
160  if (x.token_type != afw_command_local_parse_token_type_end_of_line) {
161  AFW_THROW_ERROR_FZ(general, xctx,
162  "Line %" AFW_SIZE_T_FMT ": Expecting end of line",
163  x.line_number);
164  }
165  if (x.cursor >= x.end) {
166  return (const afw_memory_t *)&afw_s_a_empty_string;
167  }
168 
169  /* Process all headers. */
170  for (;;) {
171  x.line_number++;
172 
173  impl_get_token(&x);
174 
175  /* Second end of line starts payload. */
176  if (x.token_type == afw_command_local_parse_token_type_end_of_line) {
177  payload = afw_xctx_malloc_type(afw_memory_t, xctx);
178  payload->ptr = (const afw_byte_t *)x.cursor;
179  payload->size = x.end - x.cursor;
180  return payload;
181  }
182 
183  /* End of input indicates no payload. */
184  if (x.token_type == afw_command_local_parse_token_type_end_of_input) {
185  return (const afw_memory_t *)&afw_s_a_empty_string;
186  }
187 
188  /* name */
189  if (x.token_type != afw_command_local_parse_token_type_string) {
190  AFW_THROW_ERROR_FZ(general, xctx,
191  "Line %" AFW_SIZE_T_FMT ": Expecting header name",
192  x.line_number);
193  }
194  name = x.string;
195 
196  /* colon */
197  impl_get_token(&x);
198  if (x.token_type != afw_command_local_parse_token_type_colon) {
199  AFW_THROW_ERROR_FZ(general, xctx,
200  "Line %" AFW_SIZE_T_FMT ": Expecting colon",
201  x.line_number);
202  }
203 
204  /* value */
205  impl_get_token(&x);
206  if (x.token_type != afw_command_local_parse_token_type_string) {
207  AFW_THROW_ERROR_FZ(general, xctx,
208  "Line %" AFW_SIZE_T_FMT ": Expecting header value",
209  x.line_number);
210  }
211 
212  /* Add header to properties. */
213  afw_object_set_property_as_string(self->this_request_properties,
214  name, x.string, xctx);
215 
216  /* EOL */
217  impl_get_token(&x);
218  if (x.token_type != afw_command_local_parse_token_type_end_of_line) {
219  AFW_THROW_ERROR_FZ(general, xctx,
220  "Line %" AFW_SIZE_T_FMT ": Expecting end of line",
221  x.line_number);
222  }
223  }
224 
225  return payload;
226 }
227 
Adaptive Framework Core API.
#define AFW_COMMAND_DEFINE_INTERNAL(type)
Define an internal function for /src/afw_command/ source*.c files.
Adaptive Framework afw command internal header.
Parse function to support afw command local server.
afw_object_set_property_as_string(const afw_object_t *object, const afw_utf8_t *property_name, const afw_utf8_t *internal, afw_xctx_t *xctx)
Set property function for data type string values.
unsigned char afw_byte_t
A byte of memory (unsigned).
Definition: afw_common.h:208
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
#define AFW_SIZE_T_FMT
Format string specifier used for afw_size_t.
Definition: afw_common.h:341
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#define afw_memory_clear(to)
Clear preallocated memory for sizeof(*(to)).
Definition: afw_memory.h:47
#define afw_utf8_create_copy(s, len, p, xctx)
Make a utf-8 sting from chars in pool specified.
Definition: afw_utf8.h:369
#define afw_xctx_malloc_type(type, xctx)
Macro to allocate uncleared memory to hold type in xctx's pool.
Definition: afw_xctx.h:223
Self typedef for afw_command_local implementation of afw_server.
Struct for memory pointer and size.
Definition: afw_common.h:505
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.