__buffered_read.c (3046B)
1 /* -*-comment-start: "//";comment-end:""-*- 2 * GNU Mes --- Maxwell Equations of Software 3 * Copyright © 2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org> 4 * 5 * This file is part of GNU Mes. 6 * 7 * GNU Mes is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or (at 10 * your option) any later version. 11 * 12 * GNU Mes is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <mes/lib.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #if !__MESC__ 26 #define __READ_BUFFER_MAX 128 27 int __read_buffer_max; 28 #else /* FIXME: We want bin/mes-mescc's x86-linux sha256sum to stay the same. */ 29 #define __READ_BUFFER_MAX 100 30 #define __read_buffer_max 100 31 #endif 32 33 struct __read_buffer 34 { 35 ssize_t size; 36 char string[__READ_BUFFER_MAX]; 37 }; 38 39 struct __read_buffer *__read_cache = 0; 40 41 void 42 __buffered_read_init (int filedes) 43 { 44 if (!__read_cache) 45 { 46 __read_cache = (struct __read_buffer *) malloc (sizeof (struct __read_buffer) * __FILEDES_MAX); 47 #if !__MESC__ 48 __read_buffer_max = __READ_BUFFER_MAX; 49 char *p = getenv ("MES_READ_BUFFER"); 50 if (p) 51 { 52 __read_buffer_max = atoi (p); 53 if (__read_buffer_max < 0) 54 __read_buffer_max = 0; 55 if (__read_buffer_max > __READ_BUFFER_MAX) 56 __read_buffer_max = __READ_BUFFER_MAX; 57 } 58 #endif 59 } 60 } 61 62 size_t 63 __buffered_read_clear (int filedes) 64 { 65 __buffered_read_init (filedes); 66 size_t size = __read_cache[filedes].size; 67 __read_cache[filedes].size = 0; 68 return size; 69 } 70 71 ssize_t 72 __buffered_read (int filedes, void *buffer, size_t size) 73 { 74 size_t todo = size; 75 __buffered_read_init (filedes); 76 struct __read_buffer *cache = &__read_cache[filedes]; 77 char *p = buffer; 78 if (!cache->size && size > __read_buffer_max) 79 return _read (filedes, buffer, size); 80 while (cache->size > 0 && todo) 81 { 82 todo--; 83 *p++ = cache->string[__read_buffer_max - cache->size--]; 84 } 85 if (todo) 86 { 87 #if !__MESC__ 88 if (todo > __read_buffer_max) 89 return size - todo + _read (filedes, p, todo); 90 if (__mes_debug () > 4) 91 { 92 eputs ("__buffered_read: "); 93 eputs (itoa (__read_buffer_max)); 94 eputs ("\n"); 95 } 96 #endif 97 ssize_t bytes = _read (filedes, cache->string, __read_buffer_max); 98 if (bytes < 0) 99 return -1; 100 if (bytes) 101 { 102 cache->size = bytes; 103 if (bytes < __read_buffer_max) 104 memmove (cache->string + __read_buffer_max - bytes, cache->string, bytes); 105 return size - todo + __buffered_read (filedes, p, todo); 106 } 107 } 108 return size - todo; 109 }