rrd based system stats
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
5.4KB

  1. /***************************************************************************
  2. * Copyright (C) 03/2010 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <stdarg.h>
  24. #include "linebuffer.h"
  25. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  26. struct lbuf {
  27. size_t size;
  28. size_t pos;
  29. char *token;
  30. char data[0];
  31. };
  32. /*
  33. * creates linebuffer with given size
  34. */
  35. struct lbuf * lbuf_create(size_t size)
  36. {
  37. struct lbuf *buf = malloc(sizeof(struct lbuf) + size);
  38. if (buf == NULL)
  39. return NULL;
  40. buf->size = size;
  41. buf->pos = 0;
  42. return buf;
  43. }
  44. /*
  45. * frees the linebuffer and all data in it
  46. */
  47. void lbuf_free(struct lbuf *buf)
  48. {
  49. free(buf);
  50. }
  51. /*
  52. * clears the linebuffer
  53. * - returns the datasize it was holding
  54. */
  55. int lbuf_clear(struct lbuf *buf)
  56. {
  57. int oldpos = buf->pos;
  58. buf->pos = 0;
  59. return oldpos;
  60. }
  61. /*
  62. * get pointer to internal data
  63. * - returns pointer to datasize
  64. */
  65. char * lbuf_getdata(struct lbuf *buf, size_t *len)
  66. {
  67. if (len != NULL)
  68. *len = buf->pos;
  69. return buf->data;
  70. }
  71. /*
  72. * appends data to the buffer
  73. * - returns the number of bytes copied
  74. */
  75. int lbuf_append(struct lbuf *buf, const char *src, size_t size)
  76. {
  77. int len = MIN(buf->size - buf->pos, size);
  78. memcpy(buf->data + buf->pos, src, len);
  79. buf->pos += len;
  80. return len;
  81. }
  82. /*
  83. * reads as much data as it can get from a FD
  84. * - returns the number of bytes read, or -1 on error
  85. */
  86. int lbuf_readfd(struct lbuf *buf, int fd)
  87. {
  88. int len = read(fd, buf->data + buf->pos, buf->size - buf->pos);
  89. if (len <= 0)
  90. return -1;
  91. buf->pos += len;
  92. return len;
  93. }
  94. /*
  95. * parses as much data as it can get from a FD
  96. * parses means: backspaces remove one byte from the end of the buffer
  97. * - returns 0 on success, or -1 on error
  98. */
  99. int lbuf_parsefd(struct lbuf *buf, int fd)
  100. {
  101. char tmp[32];
  102. int len = read(fd, tmp, sizeof(tmp));
  103. if (len <= 0)
  104. return -1;
  105. int i;
  106. for (i = 0; i < len; i++) {
  107. /* "understand" backspace */
  108. if (tmp[i] == 0x08 && buf->pos > 0) {
  109. buf->pos--;
  110. /* copy */
  111. } else if (tmp[i] >= ' ' || tmp[i] == '\n') {
  112. *(buf->data + buf->pos++) = tmp[i];
  113. }
  114. if (buf->pos > buf->size)
  115. return -1;
  116. }
  117. /* TODO: return bytes appended to buffer? */
  118. return 0;
  119. }
  120. /*
  121. * writes as much data as it can to a FD
  122. * - returns the number of bytes written, or -1 on error
  123. */
  124. int lbuf_writefd(struct lbuf *buf, int fd)
  125. {
  126. int len = write(fd, buf->data, buf->pos);
  127. if (len <= 0)
  128. return -1;
  129. /* handle partial writes */
  130. if (len != buf->pos)
  131. memmove(buf->data, buf->data + len, buf->pos - len);
  132. buf->pos -= len;
  133. return len;
  134. }
  135. /*
  136. * append va_list to buffer
  137. * - returns number ob bytes appended, or -1 on error
  138. */
  139. int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list az)
  140. {
  141. int len = vsnprintf(buf->data + buf->pos, buf->size - buf->pos, fmt, az);
  142. if (len < 0 || len >= (buf->size - buf->pos))
  143. return -1;
  144. buf->pos += len;
  145. return len;
  146. }
  147. /*
  148. * printf into buffer
  149. * - returns number of bytes appended, or -1 on error
  150. */
  151. int lbuf_printf(struct lbuf *buf, const char *fmt, ...)
  152. {
  153. va_list az;
  154. va_start(az, fmt);
  155. int ret = lbuf_vprintf(buf, fmt, az);
  156. va_end(az);
  157. return ret;
  158. }
  159. /*
  160. * get next non-empty token
  161. * - returns pointer to next token
  162. * - returns NULL if no delimter is found in buffer
  163. */
  164. char * lbuf_gettok(struct lbuf *buf, const char *delim)
  165. {
  166. char *start = buf->data;
  167. char *end = buf->data + buf->pos;
  168. int dlen = strlen(delim);
  169. while (1) {
  170. buf->token = NULL;
  171. /* find first delimiter in buffer */
  172. int i;
  173. for (i = 0; i < dlen; i++) {
  174. char *tok = memchr(start, delim[i], end - start);
  175. if (tok != NULL && (tok < buf->token || buf->token == NULL))
  176. buf->token = tok;
  177. }
  178. /* nothing found */
  179. if (buf->token == NULL)
  180. return NULL;
  181. /* delimter found on start pos -> skip empty token */
  182. if (buf->token == start) {
  183. start++;
  184. if (start >= end)
  185. return NULL;
  186. } else {
  187. /* non-empty token found, exit */
  188. break;
  189. }
  190. }
  191. /* overwrite token, return start ptr */
  192. *(buf->token) = '\0';
  193. return start;
  194. }
  195. /*
  196. * release previous fetched line
  197. * - returns number of remaining bytes in buffer
  198. */
  199. int lbuf_freetok(struct lbuf *buf)
  200. {
  201. if (buf->token != NULL) {
  202. buf->pos -= (buf->token - buf->data) +1;
  203. memmove(buf->data, buf->token +1, buf->pos);
  204. buf->token = NULL;
  205. }
  206. return buf->pos;
  207. }