1 /* 2 * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ 3 * 4 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 * Michael Clark <michael@metaparadigm.com> 6 * 7 * This library is free software; you can redistribute it and/or modify 8 * it under the terms of the MIT license. See COPYING for details. 9 * 10 * 11 * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. 12 * The copyrights to the contents of this file are licensed under the MIT License 13 * (http://www.opensource.org/licenses/mit-license.php) 14 */ 15 16 #include "config.h" 17 18 #include <limits.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #ifdef HAVE_STDARG_H 24 #include <stdarg.h> 25 #else /* !HAVE_STDARG_H */ 26 #error Not enough var arg support! 27 #endif /* HAVE_STDARG_H */ 28 29 #include "debug.h" 30 #include "printbuf.h" 31 #include "snprintf_compat.h" 32 #include "vasprintf_compat.h" 33 34 static int printbuf_extend(struct printbuf *p, int min_size); 35 36 struct printbuf *printbuf_new(void) 37 { 38 struct printbuf *p; 39 40 p = (struct printbuf *)calloc(1, sizeof(struct printbuf)); 41 if (!p) 42 return NULL; 43 p->size = 32; 44 p->bpos = 0; 45 if (!(p->buf = (char *)malloc(p->size))) 46 { 47 free(p); 48 return NULL; 49 } 50 p->buf[0] = '\0'; 51 return p; 52 } 53 54 /** 55 * Extend the buffer p so it has a size of at least min_size. 56 * 57 * If the current size is large enough, nothing is changed. 58 * 59 * Note: this does not check the available space! The caller 60 * is responsible for performing those calculations. 61 */ 62 static int printbuf_extend(struct printbuf *p, int min_size) 63 { 64 char *t; 65 int new_size; 66 67 if (p->size >= min_size) 68 return 0; 69 /* Prevent signed integer overflows with large buffers. */ 70 if (min_size > INT_MAX - 8) 71 return -1; 72 if (p->size > INT_MAX / 2) 73 new_size = min_size + 8; 74 else { 75 new_size = p->size * 2; 76 if (new_size < min_size + 8) 77 new_size = min_size + 8; 78 } 79 #ifdef PRINTBUF_DEBUG 80 MC_DEBUG("printbuf_memappend: realloc " 81 "bpos=%d min_size=%d old_size=%d new_size=%d\n", 82 p->bpos, min_size, p->size, new_size); 83 #endif /* PRINTBUF_DEBUG */ 84 if (!(t = (char *)realloc(p->buf, new_size))) 85 return -1; 86 p->size = new_size; 87 p->buf = t; 88 return 0; 89 } 90 91 int printbuf_memappend(struct printbuf *p, const char *buf, int size) 92 { 93 /* Prevent signed integer overflows with large buffers. */ 94 if (size > INT_MAX - p->bpos - 1) 95 return -1; 96 if (p->size <= p->bpos + size + 1) 97 { 98 if (printbuf_extend(p, p->bpos + size + 1) < 0) 99 return -1; 100 } 101 memcpy(p->buf + p->bpos, buf, size); 102 p->bpos += size; 103 p->buf[p->bpos] = '\0'; 104 return size; 105 } 106 107 int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) 108 { 109 int size_needed; 110 111 if (offset == -1) 112 offset = pb->bpos; 113 /* Prevent signed integer overflows with large buffers. */ 114 if (len > INT_MAX - offset) 115 return -1; 116 size_needed = offset + len; 117 if (pb->size < size_needed) 118 { 119 if (printbuf_extend(pb, size_needed) < 0) 120 return -1; 121 } 122 123 memset(pb->buf + offset, charvalue, len); 124 if (pb->bpos < size_needed) 125 pb->bpos = size_needed; 126 127 return 0; 128 } 129 130 int sprintbuf(struct printbuf *p, const char *msg, ...) 131 { 132 va_list ap; 133 char *t; 134 int size; 135 char buf[128]; 136 137 /* user stack buffer first */ 138 va_start(ap, msg); 139 size = vsnprintf(buf, 128, msg, ap); 140 va_end(ap); 141 /* if string is greater than stack buffer, then use dynamic string 142 * with vasprintf. Note: some implementation of vsnprintf return -1 143 * if output is truncated whereas some return the number of bytes that 144 * would have been written - this code handles both cases. 145 */ 146 if (size == -1 || size > 127) 147 { 148 va_start(ap, msg); 149 if ((size = vasprintf(&t, msg, ap)) < 0) 150 { 151 va_end(ap); 152 return -1; 153 } 154 va_end(ap); 155 printbuf_memappend(p, t, size); 156 free(t); 157 return size; 158 } 159 else 160 { 161 printbuf_memappend(p, buf, size); 162 return size; 163 } 164 } 165 166 void printbuf_reset(struct printbuf *p) 167 { 168 p->buf[0] = '\0'; 169 p->bpos = 0; 170 } 171 172 void printbuf_free(struct printbuf *p) 173 { 174 if (p) 175 { 176 free(p->buf); 177 free(p); 178 } 179 } 180
This page was automatically generated by LXR 0.3.1. • OpenWrt