Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_stream.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Implementation of afw_xctx interface
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 /* Get stream by streamId. */
18 AFW_DEFINE(void)
20  const afw_utf8_t *streamId,
21  const afw_stream_t **stream,
22  afw_size_t *streamNumber,
23  afw_xctx_t *xctx)
24 {
25  const afw_stream_t * const *streams;
26  afw_size_t number;
27 
28  *stream = NULL;
29  *streamNumber = -1;
30  if (xctx->stream_anchor) {
31  if (afw_utf8_equal(streamId, &afw_s_stdout)) {
32  *stream = afw_stream_standard(stdout, xctx);
33  *streamNumber = (afw_size_t)afw_stream_number_stdout;
34  }
35  else if (afw_utf8_equal(streamId, &afw_s_stderr)) {
36  *stream = afw_stream_standard(stderr, xctx);
37  *streamNumber = (afw_size_t)afw_stream_number_stderr;
38  }
39  else if (afw_utf8_equal(streamId, &afw_s_console)) {
40  *stream = afw_stream_standard(console, xctx);
41  *streamNumber = (afw_size_t)afw_stream_number_console;
42  }
43  else if (afw_utf8_equal(streamId, &afw_s_response_body)) {
44  *stream = afw_stream_standard(response_body, xctx);
45  *streamNumber = (afw_size_t)afw_stream_number_response_body;
46  }
47  else if (afw_utf8_equal(streamId, &afw_s_raw_response_body)) {
48  *stream = afw_stream_standard(raw_response_body, xctx);
49  *streamNumber = (afw_size_t)afw_stream_number_raw_response_body;
50  }
51  else for (streams = xctx->stream_anchor->streams,
52  number = afw_stream_number_count;
53  number < xctx->stream_anchor->maximum_number_of_streams;
54  streams++, number++)
55  {
56  if (afw_utf8_equal((*streams)->streamId, streamId)) {
57  *stream = *streams;
58  break;
59  }
60  }
61  }
62 }
63 
64 
65 
66 /* Get stream by streamNumber. */
67 AFW_DEFINE(const afw_stream_t *)
69  const afw_integer_t streamNumber,
70  afw_xctx_t *xctx)
71 {
72  const afw_stream_t *stream;
73  afw_size_t number;
74 
75  if (streamNumber >= 0 && streamNumber < afw_stream_number_count) {
76  stream = afw_stream_standard_impl(
77  (afw_stream_number_t)streamNumber, xctx);
78  return stream;
79  }
80 
81  number = (afw_size_t)streamNumber;
82  stream = NULL;
83  if (xctx->stream_anchor &&
84  streamNumber >= 0 &&
85  number == streamNumber &&
86  number < xctx->stream_anchor->maximum_number_of_streams)
87  {
88  stream = xctx->stream_anchor->streams[number];
89  }
90  return stream;
91 }
92 
93 
94 
95 /* Get streamNumber for streamId. */
98  const afw_utf8_t *streamId,
99  afw_xctx_t *xctx)
100 {
101  const afw_stream_t *stream;
102  afw_size_t streamNumber;
103 
105  &stream, &streamNumber, xctx);
106 
107  return streamNumber;
108 }
109 
110 
111 
112 /* Get streamNumber for streamId. */
115  const afw_stream_t *stream,
116  afw_xctx_t *xctx)
117 {
118  const afw_stream_t **streams;
119  afw_size_t count, number;
120 
121  number = -1;
122  if (xctx->stream_anchor) {
123  for (streams = (const afw_stream_t **)xctx->stream_anchor->streams,
124  count = 0;
125  count < xctx->stream_anchor->maximum_number_of_streams;
126  count++, streams++)
127  {
128  if (*streams) {
129  if (afw_utf8_equal((*streams)->streamId, stream->streamId))
130  {
131  return -1;
132  }
133  }
134  else if (number == -1) {
135  number = count;
136  }
137  }
138  if (number != -1) {
139  streams[number] = stream;
140  }
141  }
142 
143  return number;
144 }
145 
146 
147 
148 /* Implementation for get xctx writer instance. */
149 AFW_DEFINE(const afw_stream_t *)
151 {
152  const afw_content_type_t *response_content_type;
153  afw_stream_anchor_t *stream_anchor =
154  (afw_stream_anchor_t *)xctx->stream_anchor;
155  const afw_stream_t **stream;
156 
157  if (n < 0 || n >= afw_stream_number_count) {
158  AFW_THROW_ERROR_Z(general,
159  "afw_stream_standard_impl() n parameter out of range",
160  xctx);
161  }
162 
163  response_content_type = (xctx->request)
164  ? afw_request_prepare_response_content_type(xctx->request, xctx)
165  : NULL;
166 
167  if (!stream_anchor->streams[n]) {
168  stream = (const afw_stream_t **)&stream_anchor->streams[n];
169  switch (n) {
170 
171  case afw_stream_number_raw_response_body:
172  if (xctx->request) {
173  *stream = afw_request_response_body_raw_writer_create(
174  xctx->request, xctx);
175  }
176  else {
177  *stream = afw_stream_fd_create(xctx->env->stdout_fd,
178  &afw_s_raw_response_body, false, true, true, false,
179  xctx->p, xctx);
180  }
181  break;
182 
183  case afw_stream_number_response_body:
184  if (afw_content_type_is_application_afw(response_content_type))
185  {
187  afw_stream_standard(raw_response_body, xctx),
188  &afw_s_response, NULL, xctx->p, xctx);
189  }
190  else {
191  *stream = afw_stream_standard(raw_response_body, xctx);
192  }
193  break;
194 
195  case afw_stream_number_console:
197  &afw_s_a_flag_response_console_stream, xctx))
198  {
199  if (afw_content_type_is_application_afw(response_content_type))
200  {
202  afw_stream_standard(raw_response_body, xctx),
203  &afw_s_console, NULL, xctx->p, xctx);
204  }
205  else {
206  AFW_THROW_ERROR_Z(general,
207  "flag response:console:stream requires content-type "
208  "application/x-afw",
209  xctx);
210  }
211  }
212  else if (afw_flag_by_id_is_active(
213  &afw_s_a_flag_response_console, xctx))
214  {
215  *stream = afw_utf8_stream_create(&afw_s_console,
216  xctx->p, xctx);
217  }
218  else {
219  *stream = afw_stream_fd_create(xctx->env->stdout_fd,
220  &afw_s_console, false, true, true, false, xctx->p, xctx);
221  }
222  break;
223 
224  case afw_stream_number_stderr:
226  &afw_s_a_flag_response_stderr_stream, xctx))
227  {
228  if (afw_content_type_is_application_afw(response_content_type))
229  {
231  afw_stream_standard(raw_response_body, xctx),
232  &afw_s_stderr, NULL, xctx->p, xctx);
233  }
234  else {
235  AFW_THROW_ERROR_Z(general,
236  "flag response:stderr:stream requires content-type "
237  "application/x-afw",
238  xctx);
239  }
240  }
241  else if (afw_flag_by_id_is_active(
242  &afw_s_a_flag_response_stderr, xctx))
243  {
244  *stream = afw_utf8_stream_create(&afw_s_stderr,
245  xctx->p, xctx);
246  }
247  else {
248  *stream = afw_stream_fd_create(xctx->env->stdout_fd,
249  &afw_s_stderr, false, true, true, false, xctx->p, xctx);
250  }
251  break;
252 
253  case afw_stream_number_stdout:
255  &afw_s_a_flag_response_stdout_stream, xctx))
256  {
257  if (afw_content_type_is_application_afw(response_content_type))
258  {
260  afw_stream_standard(raw_response_body, xctx),
261  &afw_s_stdout, NULL, xctx->p, xctx);
262  }
263  else {
264  AFW_THROW_ERROR_Z(general,
265  "flag response:stdout:stream requires content-type "
266  "application/x-afw",
267  xctx);
268  }
269  }
270  else if (afw_flag_by_id_is_active(
271  &afw_s_a_flag_response_stdout, xctx))
272  {
273  *stream = afw_utf8_stream_create(&afw_s_stdout,
274  xctx->p, xctx);
275  }
276  else {
277  *stream = afw_stream_fd_create(xctx->env->stdout_fd,
278  &afw_s_stdout, false, true, true, false, xctx->p, xctx);
279  }
280  break;
281 
282  default:
283  AFW_THROW_ERROR_Z(general, "Internal error", xctx);
284  }
285  }
286 
287  return stream_anchor->streams[n];
288 }
289 
290 
297 afw_stream_internal_stream_anchor_create(afw_xctx_t *xctx)
298 {
299  afw_stream_anchor_t *stream_anchor;
300 
301  stream_anchor = apr_pcalloc(afw_pool_get_apr_pool(xctx->p),
302  sizeof(afw_stream_anchor_t));
303  stream_anchor->maximum_number_of_streams = afw_stream_number_count + 20;
304  stream_anchor->streams = apr_pcalloc(afw_pool_get_apr_pool(xctx->p),
305  stream_anchor->maximum_number_of_streams * sizeof(afw_stream_t *));
306 
307  return stream_anchor;
308 }
309 
310 
311 /* Release xctx streams. */
313 afw_stream_internal_release_all_streams(afw_xctx_t *xctx)
314 {
316 
317  /* Release writers. */
318  for (i = 0; i < afw_stream_number_count; i++) {
319  if (xctx->stream_anchor->streams[i] &&
320  i != afw_stream_number_raw_response_body)
321  {
322  afw_stream_release(xctx->stream_anchor->streams[i], xctx);
323  *(afw_stream_t **)&xctx->stream_anchor->streams[i] = NULL;
324  }
325  }
326 
327  /* Release raw_response_body last. */
328  if (afw_stream_standard(raw_response_body, xctx)) {
330  afw_stream_standard(raw_response_body, xctx), xctx);
331  *(afw_stream_t **)
332  &xctx->stream_anchor->streams[afw_stream_number_raw_response_body]
333  = NULL;
334  }
335 }
336 
337 
338 
339 /* Call afw_stream_write() with an integer. */
340 AFW_DEFINE(void)
342  const afw_stream_t *writer,
343  afw_integer_t integer,
344  afw_xctx_t *xctx)
345 {
346  char buf[AFW_INTEGER_MAX_BUFFER];
347 
348  snprintf(buf, AFW_INTEGER_MAX_BUFFER, "%" AFW_INTEGER_FMT,
349  integer);
350  afw_stream_write_z(writer, buf, xctx);
351 }
352 
353 
354 
355 /* Call afw_stream_write() with a size. */
356 AFW_DEFINE(void)
358  const afw_stream_t *writer,
359  afw_size_t size,
360  afw_xctx_t *xctx)
361 {
362  char buf[AFW_SIZE_T_MAX_BUFFER];
363 
364  snprintf(buf, AFW_SIZE_T_MAX_BUFFER, "%" AFW_SIZE_T_FMT,
365  size);
366  afw_stream_write_z(writer, buf, xctx);
367 }
AFW_DEFINE(const afw_object_t *)
#define AFW_DEFINE_INTERNAL(type)
Define an internal function for /src/afw/ source*.c files.
Adaptive Framework Core Internal.
#define AFW_SIZE_T_MAX_BUFFER
this is the maximum number of digits that can be produced by afw_size_t plus null terminator.
Definition: afw_common.h:362
#define AFW_INTEGER_FMT
Format string specifier used for afw_integer_t.
Definition: afw_common.h:326
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_SIZE_T_FMT
Format string specifier used for afw_size_t.
Definition: afw_common.h:341
#define AFW_INTEGER_MAX_BUFFER
this is the maximum number of digits that can be produced by afw_integer_t plus negative sign plus nu...
Definition: afw_common.h:275
apr_int64_t afw_integer_t
typedef for big signed int.
Definition: afw_common.h:321
#define afw_content_type_is_application_afw(instance)
Determine if content type it application/x-afw.
const afw_stream_t * afw_content_type_application_afw_stream_create(const afw_stream_t *response_stream, const afw_utf8_t *streamId, const afw_utf8_t *info, const afw_pool_t *p, afw_xctx_t *xctx)
Create a stream for content type application/afw.
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
afw_boolean_t afw_flag_by_id_is_active(const afw_utf8_t *flag_id, afw_xctx_t *xctx)
Determine if flag for flag id is set in xctx.
Definition: afw_flag.c:565
#define afw_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
#define afw_stream_release(instance, xctx)
Call method release of interface afw_stream.
afw_stream_standard_impl(afw_stream_number_t n, afw_xctx_t *xctx)
Implementation for get xctx standard stream instance.
Definition: afw_stream.c:150
afw_stream_get_by_streamNumber(const afw_integer_t streamNumber, afw_xctx_t *xctx)
Get stream by streamNumber.
Definition: afw_stream.c:68
afw_stream_set(const afw_stream_t *stream, afw_xctx_t *xctx)
Set an opening stream and get its streamNumber.
Definition: afw_stream.c:114
#define afw_stream_write_z(writer, s_z, xctx)
Call afw_stream_write() with zero terminated string.
Definition: afw_stream.h:178
afw_stream_get_streamNumber_for_streamId(const afw_utf8_t *streamId, afw_xctx_t *xctx)
Get streamNumber for streamId.
Definition: afw_stream.c:97
const afw_stream_t * afw_stream_fd_create(FILE *fd, const afw_utf8_t *streamId, afw_boolean_t allow_read, afw_boolean_t allow_write, afw_boolean_t auto_flush, afw_boolean_t close_on_release, const afw_pool_t *p, afw_xctx_t *xctx)
Create a stream to a file descriptor.
#define afw_stream_standard(enum_suffix, xctx)
Get xctx stream instance.
Definition: afw_stream.h:122
afw_stream_get_by_streamId(const afw_utf8_t *streamId, const afw_stream_t **stream, afw_size_t *streamNumber, afw_xctx_t *xctx)
Get stream by streamId and streamNumber.
Definition: afw_stream.c:19
afw_stream_number_t
enum for common xctx streams
Definition: afw_stream.h:31
afw_stream_write_integer(const afw_stream_t *writer, afw_integer_t integer, afw_xctx_t *xctx)
Call afw_stream_write() with an integer.
Definition: afw_stream.c:341
afw_stream_write_size(const afw_stream_t *writer, afw_size_t size, afw_xctx_t *xctx)
Call afw_stream_write() with an size.
Definition: afw_stream.c:357
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
const afw_stream_t * afw_utf8_stream_create(const afw_utf8_t *streamId, const afw_pool_t *p, afw_xctx_t *xctx)
Create UTF-8 stream.
Interface afw_content_type public struct.
struct for common xctx streams
Definition: afw_stream.h:42
Interface afw_stream public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.