Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_stream_fd.c
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Helpers for interfaces afw_writer*
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 
18 /* FIXME Add include for headers and anything else you want in this part of code. */
19 
20 /* Declares and rti/inf defines for interface afw_writer */
21 #define AFW_IMPLEMENTATION_ID "afw_stream_fd"
23 
24 
25 /* FIXME If you prefer, you can move this struct to a .h file. */
26 /* Self typedef for afw_stream_fd implementation of afw_writer. */
27 typedef struct
29  afw_stream_t pub;
30  FILE *fd;
31  afw_boolean_t auto_flush;
32  afw_boolean_t close_on_release;
34 
35 
36 
37 /*
38  * Implementation of method write_eol for interface afw_writer.
39  */
40 static afw_size_t
41 impl_afw_stream_fd_write_cb(
42  void *context,
43  const void *buffer,
44  afw_size_t size,
45  const afw_pool_t *p,
46  afw_xctx_t *xctx)
47 {
48  afw_stream_fd_self_t *self =
49  (afw_stream_fd_self_t *)context;
50  size_t len;
51 
53  if (size != 0) {
54  len = fwrite(buffer, size, 1, self->fd);
55  if (len == 0) {
56  AFW_THROW_ERROR_RV_Z(general, NULL, ferror(self->fd),
57  "fwrite() failed",
58  xctx);
59  }
60  }
61  return size;
62 }
63 
64 /*
65  * Implementation of method release for interface afw_writer.
66  */
67 void
68 impl_afw_stream_release(
69  const afw_stream_t *instance,
70  afw_xctx_t *xctx)
71 {
72  afw_stream_fd_self_t *self =
73  (afw_stream_fd_self_t *)instance;
74 
75  if (self->close_on_release) {
76  fclose(self->fd);
77  }
78 }
79 
80 /*
81  * Implementation of method flush for interface afw_writer.
82  */
83 void
84 impl_afw_stream_flush(
85  const afw_stream_t *instance,
86  afw_xctx_t *xctx)
87 {
88  afw_stream_fd_self_t *self =
89  (afw_stream_fd_self_t *)instance;
90 
91  fflush(self->fd);
92 }
93 
94 /*
95  * Implementation of method read for interface afw_stream.
96  */
97 void
99  const afw_stream_t *instance,
100  const void *buffer,
101  afw_size_t size,
102  afw_xctx_t *xctx)
103 {
105  AFW_THROW_ERROR_Z(general, "Method not implemented.", xctx);
106 }
107 
108 /*
109  * Implementation of method write for interface afw_writer.
110  */
111 void
113  const afw_stream_t *instance,
114  const void *buffer,
115  afw_size_t size,
116  afw_xctx_t *xctx)
117 {
118  afw_stream_fd_self_t *self =
119  (afw_stream_fd_self_t *)instance;
120  size_t len;
121 
123  if (size != 0) {
124  len = fwrite(buffer, size, 1, self->fd);
125  if (len == 0) {
126  AFW_THROW_ERROR_RV_Z(general, NULL, ferror(self->fd),
127  "fwrite() failed",
128  xctx);
129  }
130  if (self->auto_flush) {
131  fflush(self->fd);
132  }
133  }
134 }
135 
136 /* Create a writer to a file descriptor. */
137 AFW_DEFINE(const afw_stream_t *)
139  FILE *fd,
140  const afw_utf8_t *streamId,
141  afw_boolean_t allow_read,
142  afw_boolean_t allow_write,
143  afw_boolean_t auto_flush,
144  afw_boolean_t close_on_release,
145  const afw_pool_t *p,
146  afw_xctx_t *xctx)
147 {
148  afw_stream_fd_self_t *self;
149 
150  /*
151  * You may want to create a new pool for instance, but will just use
152  * xctx's pool in this example.
153  */
155  self->pub.inf = &impl_afw_stream_inf;
156  self->pub.p = p;
157  self->pub.streamId = streamId;
158  self->pub.write_cb = impl_afw_stream_fd_write_cb;
159  self->fd = fd;
160  self->auto_flush = auto_flush;
161  self->close_on_release = close_on_release;
162 
163  /* Return new instance. */
164  return (afw_stream_t *)self;
165 }
166 
167 
168 
169 /* Open a file and create a stream for it. */
170 AFW_DECLARE(const afw_stream_t *)
172  const afw_utf8_t *streamId,
173  const afw_utf8_t *path,
174  const afw_utf8_t *mode,
175  afw_boolean_t auto_flush,
176  const afw_pool_t *p,
177  afw_xctx_t *xctx)
178 {
179  const afw_stream_t *stream;
180  const afw_utf8_z_t *actual_path_z;
181  const afw_utf8_z_t *mode_z;
182  const afw_utf8_z_t *c;
183  FILE *fd;
184  afw_boolean_t allow_read;
185  afw_boolean_t allow_write;
186 
188  actual_path_z = afw_utf8_to_utf8_z(mode, p, xctx);
189 
190  mode_z = afw_utf8_to_utf8_z(mode, p, xctx);
191  fd = fopen(actual_path_z, mode_z);
192  if (!fd) {
193  AFW_THROW_ERROR_FZ(general, xctx,
194  "streamId %" AFW_UTF8_FMT " failed to open: %s",
195  AFW_UTF8_FMT_ARG(streamId), strerror(errno));
196  }
197 
198  allow_read = false;
199  allow_write = false;
200  for (c = mode_z; *c; c++) {
201  if (*c == 'r') {
202  allow_read = true;
203  }
204  else if (*c == 'w' || *c == 'a') {
205  allow_write = true;
206  }
207  else if (*c == '+') {
208  allow_read = true;
209  allow_write = true;
210  }
211  }
212  stream = afw_stream_fd_create(fd, streamId,
213  allow_read, allow_write, auto_flush, true, p, xctx);
214 
215  return stream;
216 }
AFW_DEFINE(const afw_object_t *)
#define AFW_DECLARE(type)
Declare a public afw function.
Adaptive Framework Core Internal.
Interface afw_interface implementation declares.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
_Bool afw_boolean_t
Definition: afw_common.h:373
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
Definition: afw_common.h:523
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_THROW_ERROR_RV_Z(code, rv_source_id, rv, message_z, xctx)
Macro used to set error and rv in xctx and throw it.
Definition: afw_error.h:301
#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_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
void impl_afw_stream_write(const afw_stream_t *instance, const void *buffer, afw_size_t size, afw_xctx_t *xctx)
void impl_afw_stream_read(const afw_stream_t *instance, const void *buffer, afw_size_t size, afw_xctx_t *xctx)
Definition: afw_stream_fd.c:98
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.
const afw_stream_t * afw_stream_fd_open_and_create(const afw_utf8_t *streamId, const afw_utf8_t *path, const afw_utf8_t *mode, afw_boolean_t auto_flush, const afw_pool_t *p, afw_xctx_t *xctx)
Open a file and create a stream for it.
const afw_utf8_z_t * afw_utf8_to_utf8_z(const afw_utf8_t *string, const afw_pool_t *p, afw_xctx_t *xctx)
Convert utf8 to utf8_z in specified pool.
Definition: afw_utf8.h:529
#define afw_xctx_calloc_type(type, xctx)
Macro to allocate cleared memory to hold type in xctx's pool.
Definition: afw_xctx.h:199
Interface afw_pool public struct.
Interface afw_stream public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.