LCOV - code coverage report
Current view: top level - common/stream - memio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 120 65.8 %
Date: 2024-10-03 20:03:20 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      207232 : buffer_init(buffer *restrict b, char *restrict buf, size_t size)
      20             : {
      21      207232 :         if (b == NULL || buf == NULL)
      22             :                 return;
      23      207232 :         b->pos = 0;
      24      207232 :         b->buf = buf;
      25      207232 :         b->len = size;
      26             : }
      27             : 
      28             : buffer *
      29         527 : buffer_create(size_t size)
      30             : {
      31         527 :         buffer *b;
      32             : 
      33         527 :         if ((b = malloc(sizeof(*b))) == NULL)
      34             :                 return NULL;
      35         527 :         *b = (buffer) {
      36         527 :                 .buf = malloc(size),
      37             :                 .len = size,
      38             :         };
      39         527 :         if (b->buf == NULL) {
      40           0 :                 free(b);
      41           0 :                 return NULL;
      42             :         }
      43             :         return b;
      44             : }
      45             : 
      46             : char *
      47         225 : buffer_get_buf(buffer *b)
      48             : {
      49         225 :         char *r;
      50             : 
      51         225 :         if (b == NULL)
      52             :                 return NULL;
      53         225 :         if (b->pos == b->len) {
      54           0 :                 if ((r = realloc(b->buf, b->len + 1)) == NULL) {
      55             :                         /* keep b->buf in tact */
      56             :                         return NULL;
      57             :                 }
      58           0 :                 b->buf = r;
      59             :         }
      60         225 :         r = b->buf;
      61         225 :         r[b->pos] = '\0';
      62         225 :         b->buf = malloc(b->len);
      63         225 :         if (b->buf == NULL) {
      64             :                 /* restore b->buf */
      65           0 :                 b->buf = r;
      66           0 :                 return NULL;
      67             :         }
      68         225 :         b->pos = 0;
      69         225 :         return r;
      70             : }
      71             : 
      72             : void
      73      207759 : buffer_destroy(buffer *b)
      74             : {
      75      207759 :         if (b == NULL)
      76             :                 return;
      77      207759 :         if (b->buf)
      78      207759 :                 free(b->buf);
      79      207759 :         free(b);
      80             : }
      81             : 
      82             : buffer *
      83           0 : mnstr_get_buffer(stream *s)
      84             : {
      85           0 :         if (s == NULL)
      86             :                 return NULL;
      87           0 :         buffer *b = (buffer *) s->stream_data.p;
      88           0 :         if (b == NULL)
      89             :                 return NULL;
      90           0 :         if (!s->readonly) {
      91             :                 /* switching from write mode to read mode */
      92           0 :                 s->readonly = true;
      93           0 :                 b->len = b->pos;
      94             :         }
      95           0 :         b->pos = 0;
      96           0 :         return b;
      97             : }
      98             : 
      99             : static ssize_t
     100      207232 : buffer_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
     101             : {
     102      207232 :         size_t size = elmsize * cnt;
     103      207232 :         buffer *b;
     104             : 
     105      207232 :         b = (buffer *) s->stream_data.p;
     106      207232 :         assert(b);
     107      207232 :         if (b == NULL)
     108             :                 return -1;
     109      207232 :         if (size != 0) {
     110      207232 :                 if (size + b->pos > b->len)
     111           0 :                         size = b->len - b->pos;
     112      207232 :                 memcpy(buf, b->buf + b->pos, size);
     113      207232 :                 b->pos += size;
     114      207232 :                 return (ssize_t) (size / elmsize);
     115             :         }
     116           0 :         s->eof |= b->pos == b->len;
     117           0 :         return 0;
     118             : }
     119             : 
     120             : static ssize_t
     121       47328 : buffer_write(stream *restrict s, const void *restrict buf, size_t elmsize, size_t cnt)
     122             : {
     123       47328 :         size_t size = elmsize * cnt;
     124       47328 :         buffer *b;
     125             : 
     126       47328 :         b = (buffer *) s->stream_data.p;
     127       47328 :         assert(b);
     128       47328 :         if (b == NULL) {
     129             :                 mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer already deallocated");
     130             :                 return -1;
     131             :         }
     132       47328 :         if (b->pos + size > b->len) {
     133          15 :                 char *p;
     134          15 :                 size_t ns = b->pos + size + 8192;
     135             : 
     136          15 :                 if ((p = realloc(b->buf, ns)) == NULL) {
     137           0 :                         mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer reallocation failed");
     138           0 :                         return -1;
     139             :                 }
     140          15 :                 b->buf = p;
     141          15 :                 b->len = ns;
     142             :         }
     143       47328 :         memcpy(b->buf + b->pos, buf, size);
     144       47328 :         b->pos += size;
     145       47328 :         return (ssize_t) cnt;
     146             : }
     147             : 
     148             : static void
     149      207759 : buffer_close(stream *s)
     150             : {
     151      207759 :         (void) s;
     152      207759 : }
     153             : 
     154             : static int
     155           0 : buffer_flush(stream *s, mnstr_flush_level flush_level)
     156             : {
     157           0 :         buffer *b;
     158             : 
     159           0 :         b = (buffer *) s->stream_data.p;
     160           0 :         assert(b);
     161           0 :         if (b == NULL)
     162             :                 return -1;
     163           0 :         b->pos = 0;
     164           0 :         (void) flush_level;
     165           0 :         return 0;
     166             : }
     167             : 
     168             : static void
     169           0 : buffer_destroy_stream(stream *s)
     170             : {
     171           0 :         buffer_destroy(s->stream_data.p);
     172           0 :         destroy_stream(s);
     173           0 : }
     174             : 
     175             : stream *
     176      207232 : buffer_rastream(buffer *restrict b, const char *restrict name)
     177             : {
     178      207232 :         stream *s;
     179             : 
     180      207232 :         if (b == NULL || name == NULL) {
     181           0 :                 mnstr_set_open_error(name, 0, "no buffer or no name");
     182           0 :                 return NULL;
     183             :         }
     184             : #ifdef STREAM_DEBUG
     185             :         fprintf(stderr, "buffer_rastream %s\n", name);
     186             : #endif
     187      207232 :         if ((s = create_stream(name)) == NULL)
     188             :                 return NULL;
     189      207232 :         s->binary = false;
     190      207232 :         s->read = buffer_read;
     191      207232 :         s->write = buffer_write;
     192      207232 :         s->close = buffer_close;
     193      207232 :         s->flush = buffer_flush;
     194      207232 :         s->stream_data.p = (void *) b;
     195      207232 :         return s;
     196             : }
     197             : 
     198             : stream *
     199         527 : buffer_wastream(buffer *restrict b, const char *restrict name)
     200             : {
     201         527 :         stream *s;
     202             : 
     203         527 :         if (name == NULL) {
     204           0 :                 mnstr_set_open_error(name, 0, "no name");
     205           0 :                 return NULL;
     206             :         }
     207             : #ifdef STREAM_DEBUG
     208             :         fprintf(stderr, "buffer_wastream %s\n", name);
     209             : #endif
     210         527 :         if ((s = create_stream(name)) == NULL)
     211             :                 return NULL;
     212         527 :         s->readonly = false;
     213         527 :         s->binary = false;
     214         527 :         s->read = buffer_read;
     215         527 :         s->write = buffer_write;
     216         527 :         s->close = buffer_close;
     217         527 :         s->flush = buffer_flush;
     218         527 :         if (b == NULL) {
     219           0 :                 b = buffer_create(1 << 20);
     220           0 :                 if (b == NULL) {
     221           0 :                         destroy_stream(s);
     222           0 :                         return NULL;
     223             :                 }
     224           0 :                 s->destroy = buffer_destroy_stream;
     225             :         }
     226         527 :         s->stream_data.p = (void *) b;
     227         527 :         return s;
     228             : }

Generated by: LCOV version 1.14