LCOV - code coverage report
Current view: top level - common/stream - memio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 118 65.3 %
Date: 2024-12-20 21:24:02 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "stream.h"
      15             : #include "stream_internal.h"
      16             : 
      17             : 
      18             : void
      19      211145 : buffer_init(buffer *restrict b, char *restrict buf, size_t size)
      20             : {
      21      211145 :         if (b == NULL || buf == NULL)
      22             :                 return;
      23      211145 :         *b = (buffer) {
      24             :                 .pos = 0,
      25             :                 .buf = buf,
      26             :                 .len = size,
      27             :         };
      28             : }
      29             : 
      30             : buffer *
      31         543 : buffer_create(size_t size)
      32             : {
      33         543 :         buffer *b;
      34             : 
      35         543 :         if ((b = malloc(sizeof(*b))) == NULL)
      36             :                 return NULL;
      37         543 :         *b = (buffer) {
      38         543 :                 .buf = malloc(size),
      39             :                 .len = size,
      40             :         };
      41         543 :         if (b->buf == NULL) {
      42           0 :                 free(b);
      43           0 :                 return NULL;
      44             :         }
      45             :         return b;
      46             : }
      47             : 
      48             : char *
      49         229 : buffer_get_buf(buffer *b)
      50             : {
      51         229 :         char *r;
      52             : 
      53         229 :         if (b == NULL)
      54             :                 return NULL;
      55         229 :         if (b->pos == b->len) {
      56           0 :                 if ((r = realloc(b->buf, b->len + 1)) == NULL) {
      57             :                         /* keep b->buf in tact */
      58             :                         return NULL;
      59             :                 }
      60           0 :                 b->buf = r;
      61             :         }
      62         229 :         r = b->buf;
      63         229 :         r[b->pos] = '\0';
      64         229 :         b->buf = malloc(b->len);
      65         229 :         if (b->buf == NULL) {
      66             :                 /* restore b->buf */
      67           0 :                 b->buf = r;
      68           0 :                 return NULL;
      69             :         }
      70         229 :         b->pos = 0;
      71         229 :         return r;
      72             : }
      73             : 
      74             : void
      75      211688 : buffer_destroy(buffer *b)
      76             : {
      77      211688 :         if (b == NULL)
      78             :                 return;
      79      211688 :         if (b->buf)
      80      211688 :                 free(b->buf);
      81      211688 :         free(b);
      82             : }
      83             : 
      84             : buffer *
      85           0 : mnstr_get_buffer(stream *s)
      86             : {
      87           0 :         if (s == NULL)
      88             :                 return NULL;
      89           0 :         buffer *b = (buffer *) s->stream_data.p;
      90           0 :         if (b == NULL)
      91             :                 return NULL;
      92           0 :         if (!s->readonly) {
      93             :                 /* switching from write mode to read mode */
      94           0 :                 s->readonly = true;
      95           0 :                 b->len = b->pos;
      96             :         }
      97           0 :         b->pos = 0;
      98           0 :         return b;
      99             : }
     100             : 
     101             : static ssize_t
     102      211145 : buffer_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
     103             : {
     104      211145 :         size_t size = elmsize * cnt;
     105      211145 :         buffer *b;
     106             : 
     107      211145 :         b = (buffer *) s->stream_data.p;
     108      211145 :         assert(b);
     109      211145 :         if (b == NULL)
     110             :                 return -1;
     111      211145 :         if (size != 0) {
     112      211145 :                 if (size + b->pos > b->len)
     113           0 :                         size = b->len - b->pos;
     114      211145 :                 memcpy(buf, b->buf + b->pos, size);
     115      211145 :                 b->pos += size;
     116      211145 :                 return (ssize_t) (size / elmsize);
     117             :         }
     118           0 :         s->eof |= b->pos == b->len;
     119           0 :         return 0;
     120             : }
     121             : 
     122             : static ssize_t
     123       48838 : buffer_write(stream *restrict s, const void *restrict buf, size_t elmsize, size_t cnt)
     124             : {
     125       48838 :         size_t size = elmsize * cnt;
     126       48838 :         buffer *b;
     127             : 
     128       48838 :         b = (buffer *) s->stream_data.p;
     129       48838 :         assert(b);
     130       48838 :         if (b == NULL) {
     131             :                 mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer already deallocated");
     132             :                 return -1;
     133             :         }
     134       48838 :         if (b->pos + size > b->len) {
     135          15 :                 char *p;
     136          15 :                 size_t ns = b->pos + size + 8192;
     137             : 
     138          15 :                 if ((p = realloc(b->buf, ns)) == NULL) {
     139           0 :                         mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer reallocation failed");
     140           0 :                         return -1;
     141             :                 }
     142          15 :                 b->buf = p;
     143          15 :                 b->len = ns;
     144             :         }
     145       48838 :         memcpy(b->buf + b->pos, buf, size);
     146       48838 :         b->pos += size;
     147       48838 :         return (ssize_t) cnt;
     148             : }
     149             : 
     150             : static void
     151      211688 : buffer_close(stream *s)
     152             : {
     153      211688 :         (void) s;
     154      211688 : }
     155             : 
     156             : static int
     157           0 : buffer_flush(stream *s, mnstr_flush_level flush_level)
     158             : {
     159           0 :         buffer *b;
     160             : 
     161           0 :         b = (buffer *) s->stream_data.p;
     162           0 :         assert(b);
     163           0 :         if (b == NULL)
     164             :                 return -1;
     165           0 :         b->pos = 0;
     166           0 :         (void) flush_level;
     167           0 :         return 0;
     168             : }
     169             : 
     170             : static void
     171           0 : buffer_destroy_stream(stream *s)
     172             : {
     173           0 :         buffer_destroy(s->stream_data.p);
     174           0 :         destroy_stream(s);
     175           0 : }
     176             : 
     177             : stream *
     178      211145 : buffer_rastream(buffer *restrict b, const char *restrict name)
     179             : {
     180      211145 :         stream *s;
     181             : 
     182      211145 :         if (b == NULL || name == NULL) {
     183           0 :                 mnstr_set_open_error(name, 0, "no buffer or no name");
     184           0 :                 return NULL;
     185             :         }
     186             : #ifdef STREAM_DEBUG
     187             :         fprintf(stderr, "buffer_rastream %s\n", name);
     188             : #endif
     189      211145 :         if ((s = create_stream(name)) == NULL)
     190             :                 return NULL;
     191      211145 :         s->binary = false;
     192      211145 :         s->read = buffer_read;
     193      211145 :         s->write = buffer_write;
     194      211145 :         s->close = buffer_close;
     195      211145 :         s->flush = buffer_flush;
     196      211145 :         s->stream_data.p = (void *) b;
     197      211145 :         return s;
     198             : }
     199             : 
     200             : stream *
     201         543 : buffer_wastream(buffer *restrict b, const char *restrict name)
     202             : {
     203         543 :         stream *s;
     204             : 
     205         543 :         if (name == NULL) {
     206           0 :                 mnstr_set_open_error(name, 0, "no name");
     207           0 :                 return NULL;
     208             :         }
     209             : #ifdef STREAM_DEBUG
     210             :         fprintf(stderr, "buffer_wastream %s\n", name);
     211             : #endif
     212         543 :         if ((s = create_stream(name)) == NULL)
     213             :                 return NULL;
     214         543 :         s->readonly = false;
     215         543 :         s->binary = false;
     216         543 :         s->read = buffer_read;
     217         543 :         s->write = buffer_write;
     218         543 :         s->close = buffer_close;
     219         543 :         s->flush = buffer_flush;
     220         543 :         if (b == NULL) {
     221           0 :                 b = buffer_create(1 << 20);
     222           0 :                 if (b == NULL) {
     223           0 :                         destroy_stream(s);
     224           0 :                         return NULL;
     225             :                 }
     226           0 :                 s->destroy = buffer_destroy_stream;
     227             :         }
     228         543 :         s->stream_data.p = (void *) b;
     229         543 :         return s;
     230             : }

Generated by: LCOV version 1.14