130a1828cSXin LI #include "less.h" 230a1828cSXin LI #include "xbuf.h" 330a1828cSXin LI 430a1828cSXin LI /* 530a1828cSXin LI * Initialize an expandable text buffer. 630a1828cSXin LI */ 7d713e089SXin LI public void xbuf_init(struct xbuffer *xbuf) 830a1828cSXin LI { 9*c77c4889SXin LI xbuf_init_size(xbuf, 16); 1030a1828cSXin LI } 1130a1828cSXin LI 12*c77c4889SXin LI public void xbuf_init_size(struct xbuffer *xbuf, size_t init_size) 13*c77c4889SXin LI { 14*c77c4889SXin LI xbuf->data = NULL; 15*c77c4889SXin LI xbuf->size = xbuf->end = 0; 16*c77c4889SXin LI xbuf->init_size = init_size; 17*c77c4889SXin LI } 18*c77c4889SXin LI 19*c77c4889SXin LI /* 20*c77c4889SXin LI * Free buffer space in an xbuf. 21*c77c4889SXin LI */ 22d713e089SXin LI public void xbuf_deinit(struct xbuffer *xbuf) 2330a1828cSXin LI { 2430a1828cSXin LI if (xbuf->data != NULL) 2530a1828cSXin LI free(xbuf->data); 2630a1828cSXin LI xbuf_init(xbuf); 2730a1828cSXin LI } 2830a1828cSXin LI 29*c77c4889SXin LI /* 30*c77c4889SXin LI * Set xbuf to empty. 31*c77c4889SXin LI */ 32d713e089SXin LI public void xbuf_reset(struct xbuffer *xbuf) 3330a1828cSXin LI { 3430a1828cSXin LI xbuf->end = 0; 3530a1828cSXin LI } 3630a1828cSXin LI 3730a1828cSXin LI /* 38*c77c4889SXin LI * Add a byte to an xbuf. 3930a1828cSXin LI */ 40d713e089SXin LI public void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b) 4130a1828cSXin LI { 4230a1828cSXin LI if (xbuf->end >= xbuf->size) 4330a1828cSXin LI { 44d713e089SXin LI unsigned char *data; 45*c77c4889SXin LI if (ckd_add(&xbuf->size, xbuf->size, xbuf->size ? xbuf->size : xbuf->init_size)) 46d713e089SXin LI out_of_memory(); 47d713e089SXin LI data = (unsigned char *) ecalloc(xbuf->size, sizeof(unsigned char)); 4830a1828cSXin LI if (xbuf->data != NULL) 4930a1828cSXin LI { 5030a1828cSXin LI memcpy(data, xbuf->data, xbuf->end); 5130a1828cSXin LI free(xbuf->data); 5230a1828cSXin LI } 5330a1828cSXin LI xbuf->data = data; 5430a1828cSXin LI } 55*c77c4889SXin LI xbuf->data[xbuf->end++] = b; 5630a1828cSXin LI } 5795270f73SXin LI 58*c77c4889SXin LI /* 59*c77c4889SXin LI * Add a char to an xbuf. 60*c77c4889SXin LI */ 61*c77c4889SXin LI public void xbuf_add_char(struct xbuffer *xbuf, char c) 62d713e089SXin LI { 63*c77c4889SXin LI xbuf_add_byte(xbuf, (unsigned char) c); 64*c77c4889SXin LI } 65*c77c4889SXin LI 66*c77c4889SXin LI /* 67*c77c4889SXin LI * Add arbitrary data to an xbuf. 68*c77c4889SXin LI */ 69*c77c4889SXin LI public void xbuf_add_data(struct xbuffer *xbuf, constant unsigned char *data, size_t len) 70*c77c4889SXin LI { 71*c77c4889SXin LI size_t i; 72d713e089SXin LI for (i = 0; i < len; i++) 73d713e089SXin LI xbuf_add_byte(xbuf, data[i]); 74d713e089SXin LI } 75d713e089SXin LI 76*c77c4889SXin LI /* 77*c77c4889SXin LI * Remove the last byte from an xbuf. 78*c77c4889SXin LI */ 79d713e089SXin LI public int xbuf_pop(struct xbuffer *buf) 8095270f73SXin LI { 8195270f73SXin LI if (buf->end == 0) 8295270f73SXin LI return -1; 83d713e089SXin LI return (int) buf->data[--(buf->end)]; 8495270f73SXin LI } 8595270f73SXin LI 86*c77c4889SXin LI /* 87*c77c4889SXin LI * Set an xbuf to the contents of another xbuf. 88*c77c4889SXin LI */ 89d713e089SXin LI public void xbuf_set(struct xbuffer *dst, struct xbuffer *src) 9095270f73SXin LI { 9195270f73SXin LI xbuf_reset(dst); 92d713e089SXin LI xbuf_add_data(dst, src->data, src->end); 9395270f73SXin LI } 94d713e089SXin LI 95*c77c4889SXin LI /* 96*c77c4889SXin LI * Return xbuf data as a char*. 97*c77c4889SXin LI */ 98*c77c4889SXin LI public constant char * xbuf_char_data(constant struct xbuffer *xbuf) 99d713e089SXin LI { 100*c77c4889SXin LI return (constant char *)(xbuf->data); 101d713e089SXin LI } 102d713e089SXin LI 103d713e089SXin LI 104d713e089SXin LI /* 105d713e089SXin LI * Helper functions for the ckd_add and ckd_mul macro substitutes. 106d713e089SXin LI * These helper functions do not set *R on overflow, and assume that 107d713e089SXin LI * arguments are nonnegative, that INTMAX_MAX <= UINTMAX_MAX, and that 108d713e089SXin LI * sizeof is a reliable way to distinguish integer representations. 109d713e089SXin LI * Despite these limitations they are good enough for 'less' on all 110d713e089SXin LI * known practical platforms. For more-complicated substitutes 111d713e089SXin LI * without most of these limitations, see Gnulib's stdckdint module. 112d713e089SXin LI */ 113d713e089SXin LI #if !HAVE_STDCKDINT_H 114d713e089SXin LI /* 115d713e089SXin LI * If the integer *R can represent VAL, store the value and return FALSE. 116d713e089SXin LI * Otherwise, possibly set *R to an indeterminate value and return TRUE. 117d713e089SXin LI * R has size RSIZE, and is signed if and only if RSIGNED is nonzero. 118d713e089SXin LI */ 119*c77c4889SXin LI static lbool help_fixup(void *r, uintmax val, int rsize, int rsigned) 120d713e089SXin LI { 121d713e089SXin LI if (rsigned) 122d713e089SXin LI { 123d713e089SXin LI if (rsize == sizeof (int)) 124d713e089SXin LI { 125d713e089SXin LI int *pr = r; 126d713e089SXin LI if (INT_MAX < val) 127d713e089SXin LI return TRUE; 128f80a33eaSXin LI *pr = (int) val; 129d713e089SXin LI #ifdef LLONG_MAX 130d713e089SXin LI } else if (rsize == sizeof (long long)) 131d713e089SXin LI { 132d713e089SXin LI long long *pr = r; 133d713e089SXin LI if (LLONG_MAX < val) 134d713e089SXin LI return TRUE; 135*c77c4889SXin LI *pr = (long long) val; 136d713e089SXin LI #endif 137d713e089SXin LI #ifdef INTMAX_MAX 138d713e089SXin LI } else if (rsize == sizeof (intmax_t)) { 139d713e089SXin LI intmax_t *pr = r; 140d713e089SXin LI if (INTMAX_MAX < val) 141d713e089SXin LI return TRUE; 142*c77c4889SXin LI *pr = (intmax_t) val; 143d713e089SXin LI #endif 144d713e089SXin LI } else /* rsize == sizeof (long) */ 145d713e089SXin LI { 146d713e089SXin LI long *pr = r; 147d713e089SXin LI if (LONG_MAX < val) 148d713e089SXin LI return TRUE; 149f80a33eaSXin LI *pr = (long) val; 150d713e089SXin LI } 151d713e089SXin LI } else { 152d713e089SXin LI if (rsize == sizeof (unsigned)) { 153d713e089SXin LI unsigned *pr = r; 154d713e089SXin LI if (UINT_MAX < val) 155d713e089SXin LI return TRUE; 156f80a33eaSXin LI *pr = (unsigned) val; 157d713e089SXin LI } else if (rsize == sizeof (unsigned long)) { 158d713e089SXin LI unsigned long *pr = r; 159d713e089SXin LI if (ULONG_MAX < val) 160d713e089SXin LI return TRUE; 161f80a33eaSXin LI *pr = (unsigned long) val; 162d713e089SXin LI #ifdef ULLONG_MAX 163d713e089SXin LI } else if (rsize == sizeof (unsigned long long)) { 164*c77c4889SXin LI unsigned long long *pr = r; 165d713e089SXin LI if (ULLONG_MAX < val) 166d713e089SXin LI return TRUE; 167*c77c4889SXin LI *pr = (unsigned long long) val; 168d713e089SXin LI #endif 169d713e089SXin LI } else /* rsize == sizeof (uintmax) */ 170d713e089SXin LI { 171d713e089SXin LI uintmax *pr = r; 172*c77c4889SXin LI *pr = (uintmax) val; 173d713e089SXin LI } 174d713e089SXin LI } 175d713e089SXin LI return FALSE; 176d713e089SXin LI } 177*c77c4889SXin LI 178d713e089SXin LI /* 179d713e089SXin LI * If *R can represent the mathematical sum of A and B, store the sum 180d713e089SXin LI * and return FALSE. Otherwise, possibly set *R to an indeterminate 181d713e089SXin LI * value and return TRUE. R has size RSIZE, and is signed if and only 182d713e089SXin LI * if RSIGNED is nonzero. 183d713e089SXin LI */ 184*c77c4889SXin LI public lbool help_ckd_add(void *r, uintmax a, uintmax b, int rsize, int rsigned) 185d713e089SXin LI { 186d713e089SXin LI uintmax sum = a + b; 187d713e089SXin LI return sum < a || help_fixup(r, sum, rsize, rsigned); 188d713e089SXin LI } 189*c77c4889SXin LI 190d713e089SXin LI /* Likewise, but for the product of A and B. */ 191*c77c4889SXin LI public lbool help_ckd_mul(void *r, uintmax a, uintmax b, int rsize, int rsigned) 192d713e089SXin LI { 193d713e089SXin LI uintmax product = a * b; 194d713e089SXin LI return ((b != 0 && a != product / b) 195d713e089SXin LI || help_fixup(r, product, rsize, rsigned)); 196d713e089SXin LI } 197d713e089SXin LI #endif 198