1/* 2 * Copyright 2004, Axel D��rfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "line_buffer.h" 8 9#include <KernelExport.h> 10#include <stdlib.h> 11 12 13status_t 14clear_line_buffer(struct line_buffer &buffer) 15{ 16 buffer.in = 0; 17 buffer.first = 0; 18 return B_OK; 19} 20 21 22status_t 23init_line_buffer(struct line_buffer &buffer, size_t size) 24{ 25 clear_line_buffer(buffer); 26 27 buffer.buffer = (char *)malloc(size); 28 if (buffer.buffer == NULL) 29 return B_NO_MEMORY; 30 31 buffer.size = size; 32 33 return B_OK; 34} 35 36 37status_t 38uninit_line_buffer(struct line_buffer &buffer) 39{ 40 free(buffer.buffer); 41 return B_OK; 42} 43 44 45int32 46line_buffer_readable(struct line_buffer &buffer) 47{ 48 return buffer.in; 49} 50 51 52int32 53line_buffer_readable_line(struct line_buffer &buffer, char eol, char eof) 54{ 55 size_t size = buffer.in; 56 if (size == 0) 57 return 0; 58 59 // find EOL or EOF char 60 for (size_t i = 0; i < size; i++) { 61 char c = buffer.buffer[(buffer.first + i) % buffer.size]; 62 if (c == eol || c == '\n' || c == '\r' || c == eof) 63 return i + 1; 64 } 65 66 // If the buffer is full, but doesn't contain a EOL or EOF, we report the 67 // full size anyway, since otherwise the reader would wait forever. 68 return buffer.in == buffer.size ? buffer.in : 0; 69} 70 71 72int32 73line_buffer_writable(struct line_buffer &buffer) 74{ 75 return buffer.size - buffer.in; 76} 77 78 79ssize_t 80line_buffer_user_read(struct line_buffer &buffer, char *data, size_t length, 81 char eof, bool* hitEOF) 82{ 83 size_t available = buffer.in; 84 85 if (length > available) 86 length = available; 87 88 if (length == 0) 89 return 0; 90 91 // check for EOF, if the caller asked us to 92 if (hitEOF) { 93 *hitEOF = false; 94 for (size_t i = 0; i < available; i++) { 95 char c = buffer.buffer[(buffer.first + i) % buffer.size]; 96 if (c == eof) { 97 *hitEOF = true; 98 length = i; 99 break; 100 } 101 } 102 } 103 104 ssize_t bytesRead = length; 105 106 if (buffer.first + length < buffer.size) { 107 // simple copy 108 if (user_memcpy(data, buffer.buffer + buffer.first, length) != B_OK) 109 bytesRead = B_BAD_ADDRESS; 110 } else { 111 // need to copy both ends 112 size_t upper = buffer.size - buffer.first; 113 size_t lower = length - upper; 114 115 if (user_memcpy(data, buffer.buffer + buffer.first, upper) != B_OK 116 || user_memcpy(data + upper, buffer.buffer, lower) != B_OK) 117 bytesRead = B_BAD_ADDRESS; 118 } 119 120 if (bytesRead > 0) { 121 buffer.first = (buffer.first + bytesRead) % buffer.size; 122 buffer.in -= bytesRead; 123 } 124 125 // dispose of EOF char 126 if (hitEOF && *hitEOF) { 127 buffer.first = (buffer.first + 1) % buffer.size; 128 buffer.in--; 129 } 130 131 return bytesRead; 132} 133 134 135status_t 136line_buffer_putc(struct line_buffer &buffer, char c) 137{ 138 if (buffer.in == buffer.size) 139 return B_NO_MEMORY; 140 141 buffer.buffer[(buffer.first + buffer.in++) % buffer.size] = c; 142 return B_OK; 143} 144 145 146#if 0 147status_t 148line_buffer_getc(struct line_buffer &buffer, char *_c) 149{ 150} 151 152 153status_t 154line_buffer_ungetc(struct line_buffer &buffer, char *c) 155{ 156} 157 158#endif 159 160 161bool 162line_buffer_tail_getc(struct line_buffer &buffer, char *c) 163{ 164 if (buffer.in == 0) 165 return false; 166 167 *c = buffer.buffer[(buffer.first + --buffer.in) % buffer.size]; 168 return true; 169} 170