1 /******************************************************************************
2 @file stream_mem.c
4 @brief TIMAC 2.0 API Treat a chunk of memory as a stream
6 Group: WCS LPC
7 $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350, CC1352$
9 ******************************************************************************
10 $License: BSD3 2016 $
12 Copyright (c) 2015, Texas Instruments Incorporated
13 All rights reserved.
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
17 are met:
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
22 * Redistributions in binary form must reproduce the above copyright
23 notice, this list of conditions and the following disclaimer in the
24 documentation and/or other materials provided with the distribution.
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 its contributors may be used to endorse or promote products derived
28 from this software without specific prior written permission.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 ******************************************************************************
42 $Release Name: TI-15.4Stack Linux x64 SDK$
43 $Release Date: Sept 27, 2017 (2.04.00.13)$
44 *****************************************************************************/
46 #include "compiler.h"
48 #include "stream.h"
49 #include "void_ptr.h"
50 #define _STREAM_IMPLIMENTOR_ 1
51 #include "stream_private.h"
53 #include <string.h>
54 #include <malloc.h>
56 /*!
57 * @var mem_check
58 * @brief [private] Used to verify the details pointe is valid
59 */
60 static const int mem_check = 'M';
62 /*!
63 * @struct mem_stream_details
64 * @brief Details about the memory buffer for the stream.
65 */
67 struct mem_stream_details
68 {
69 /*! Used to verify the structure is valid */
70 const int *check_ptr;
72 /*! Owning parent stream */
73 struct io_stream *pParent;
75 /* True if this buffer can be written */
76 bool is_wr;
78 /* True if this buffer can be read */
79 bool is_rd;
81 /* points to the buffer */
82 void *pBytes;
84 /* True if the buffer was allocated */
85 bool alloc;
87 /* Rd/Wr cursor (index) within buffer where IO will occur */
88 size_t cursor;
90 /* Size in bytes of the buffer. */
91 size_t bufsiz;
92 };
94 /*!
95 * @brief extract & validate the memory stream details from this stream.
96 * @param pIO - the io stream
97 * @returns NULL on error, or a details pointer.
98 */
99 static struct mem_stream_details *getM(struct io_stream *pIO)
100 {
101 struct mem_stream_details *pM;
103 /* cast it */
104 pM = (struct mem_stream_details *)(pIO->opaque_ptr);
106 /* perform our checks */
107 if(pM)
108 {
109 if(pM->check_ptr != &mem_check)
110 {
111 pM = NULL;
112 }
113 }
114 return (pM);
115 }
117 /*!
118 * @brief [private] Method function for the memory buffer stream to close
119 * @param pIO - the io stream we are closing.
120 * @returns NULL
121 */
122 static void mem_close(struct io_stream *pIO)
123 {
124 struct mem_stream_details *pM;
126 /* Extract */
127 pM = getM(pIO);
129 /* and zap */
130 if(pM)
131 {
132 if(pM->alloc)
133 {
134 if(pM->pBytes)
135 {
136 memset((void *)(pM->pBytes), 0, pM->bufsiz);
137 free((void *)(pM->pBytes));
138 pM->pBytes = NULL;
139 }
140 memset((void*)(pM), 0, sizeof(*pM));
141 }
142 memset((void *)(pIO), 0, sizeof(*pIO));
143 }
144 }
146 /*!
147 * @brief [private] Method function for the memory buffer stream to write
148 * @param pIO - the io stream we are writing
149 * @param pBytes - pointer to the transfer buffer
150 * @param nbytes - count in bytes we are transfering
151 * @param timeout_mSecs - timeout [not used in this implmentation]
152 * @returns negative on error, or 0..actual bytes written.
153 */
154 static int mem_wr(struct io_stream *pIO,
155 const void *pBytes,
156 size_t nbytes,
157 int timeout_mSecs)
158 {
159 struct mem_stream_details *pM;
161 (void)(timeout_mSecs);
163 /* extract */
164 pM = getM(pIO);
165 if(pM == NULL)
166 {
167 return (-1);
168 }
170 /* is this legal? */
171 if(!(pM->is_wr))
172 {
173 return (-1);
174 }
176 /* check space */
177 size_t space;
178 /* bufsiz is fixed at startup, cursor will not go beyond */
179 space = pM->bufsiz - pM->cursor;
181 /* don't go beyond our buffer */
182 if(nbytes > space)
183 {
184 nbytes = space;
185 }
187 /* if so, write */
188 if(nbytes)
189 {
190 memcpy(void_ptr_add(pM->pBytes, pM->cursor), pBytes, nbytes);
191 pM->cursor += nbytes;
192 }
194 /* return actual */
195 return ((int)nbytes);
196 }
198 /*!
199 * @brief [privatge] Method function for the memory buffer stream to reading
200 * @param pIO - the io stream we are reading
201 * @param pBytes - pointer to the transfer buffer
202 * @param nbytes - count in bytes we are transfering
203 * @param timeout_mSecs - timeout [not used in this implmentation]
204 * @returns negative on error, or 0..actual bytes read
205 */
206 static int mem_rd(struct io_stream *pIO,
207 void *pBytes,
208 size_t nbytes,
209 int timeout_mSecs)
210 {
211 struct mem_stream_details *pM;
213 (void)(timeout_mSecs);
215 /* extract */
216 pM = getM(pIO);
217 if(pM == NULL)
218 {
219 return (-1);
220 }
222 /* sanity check */
223 if(!(pM->is_rd))
224 {
225 return (-1);
226 }
228 /* don't go beyond our buffer */
229 size_t avail;
230 /* bufsiz is fixed at startup, cursor will not go beyond */
231 avail = pM->bufsiz - pM->cursor;
233 if(nbytes > avail)
234 {
235 nbytes = avail;
236 }
238 /* transfer */
239 if(nbytes)
240 {
241 memcpy(pBytes, void_ptr_add(pM->pBytes, pM->cursor), nbytes);
242 pM->cursor += nbytes;
243 }
245 /* return actual */
246 return ((int)nbytes);
247 }
249 /*!
250 * @brief [private] determine if we can poll (rd) this memory buffer
251 * @param pIO - the io stream
252 * @param timeout_mSec - not used in this implimentation.
253 * @returns true if no error and not at the end of the buffer space
254 */
255 static bool mem_poll(struct io_stream *pIO, int timeout_mSec)
256 {
257 struct mem_stream_details *pM;
259 (void)(timeout_mSec);
261 /* extract */
262 pM = getM(pIO);
263 if(pM == NULL)
264 {
265 return (-1);
266 }
268 /* is it readable, and are we not at the end? */
269 if(pM->is_rd && (pM->cursor < pM->bufsiz))
270 {
271 /* then we can read */
272 return (true);
273 }
274 else
275 {
276 return (false);
277 }
278 }
280 /*!
281 * @brief [private] method to flush, we have no buffer.. this is not a FILE
282 * @param pIO - the io stream
283 */
284 static int mem_flush(struct io_stream *pIO)
285 {
286 (void)(pIO);
287 /* nothing to flush */
288 return (0);
289 }
291 /*!
292 * @var mem_funcs
293 * @brief Method function table for the memory IO routines
294 */
295 static const struct io_stream_funcs mem_funcs = {
296 .name = "string",
297 .close_fn = mem_close,
298 .wr_fn = mem_wr,
299 .rd_fn = mem_rd,
300 .poll_fn = mem_poll,
301 .flush_fn = mem_flush
302 };
304 /*!
305 * @brief [private] Common routine to create a memory buffer stream
306 * @param pBytes - the io buffer
307 * @param nBytes - the size in bytes of the io buffer
308 * @param is_wr - boolean true if this is writeable
309 * @param is_rd - boolean true if this is readable
310 * @param Returns non-zero handle on success
311 */
312 static intptr_t _mem_create(void *pBytes,
313 size_t nbytes,
314 bool is_wr,
315 bool is_rd)
316 {
317 struct mem_stream_details *pM;
319 pM = calloc(1, sizeof(*pM));
320 if(!pM)
321 {
322 return (0);
323 }
325 pM->check_ptr = &mem_check;
326 pM->is_wr = is_wr;
327 pM->is_rd = is_rd;
328 pM->pBytes = pBytes;
329 if(pM->pBytes == NULL)
330 {
331 pM->alloc = true;
332 pM->pBytes = calloc(1, nbytes+1);
333 if(pM->pBytes == NULL)
334 {
335 goto fail;
336 }
337 }
339 pM->cursor = 0;
340 pM->bufsiz = nbytes;
342 pM->pParent = STREAM_createPrivate(&mem_funcs, (intptr_t)(pM));
343 if(pM->pParent != NULL)
344 {
345 return (STREAM_structToH(pM->pParent));
346 }
347 fail:
348 if(pM->alloc)
349 {
350 free((void *)(pM->pBytes));
351 pM->pBytes = NULL;
352 }
353 memset((void*)(pM), 0, sizeof(*pM));
354 free((void *)(pM));
355 return (0);
356 }
358 /*
359 * Create a stream from a null terminated string
360 *
361 * Public function defined in stream.h
362 */
363 intptr_t STREAM_stringCreate(const char *s)
364 {
365 #if defined(__linux__)
366 #pragma GCC diagnostic push
367 #pragma GCC diagnostic ignored "-Wcast-qual"
368 #endif
369 return (_mem_create((void *)s, strlen(s), 0, 1));
370 #if defined(__linux__)
371 #pragma GCC diagnostic pop
372 #endif
373 }
375 /*
376 * Create a stream from a chunk of memory
377 *
378 * Public function defined in stream.h
379 */
380 intptr_t STREAM_memCreate(void *pBytes, size_t nbytes)
381 {
382 return (_mem_create(pBytes, nbytes, 1, 1));
383 }
385 /*
386 * ========================================
387 * Texas Instruments Micro Controller Style
388 * ========================================
389 * Local Variables:
390 * mode: c
391 * c-file-style: "bsd"
392 * tab-width: 4
393 * c-basic-offset: 4
394 * indent-tabs-mode: nil
395 * End:
396 * vim:set filetype=c tabstop=4 shiftwidth=4 expandtab=true
397 */