Annotation of embedaddon/libpdel/io/string_fp.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include <sys/types.h>
        !            42: #include <sys/param.h>
        !            43: 
        !            44: #include <stdio.h>
        !            45: #include <stdlib.h>
        !            46: #include <stdarg.h>
        !            47: #include <string.h>
        !            48: #include <assert.h>
        !            49: #include <errno.h>
        !            50: 
        !            51: #include "structs/structs.h"
        !            52: #include "structs/type/array.h"
        !            53: 
        !            54: #include "io/string_fp.h"
        !            55: #include "util/typed_mem.h"
        !            56: 
        !            57: #define ROUNDUP2(x, y)         (((x) + ((y) - 1)) & ~((y) - 1))
        !            58: 
        !            59: #ifndef __linux__
        !            60: #define GET_COOKIE(fp)         ((fp)->_cookie)
        !            61: #else
        !            62: #define GET_COOKIE(fp)         (((void **)(fp + 1))[1])
        !            63: #endif
        !            64: 
        !            65: /***********************************************************************
        !            66:                    STRING BUFFER OUTPUT STREAMS
        !            67: ***********************************************************************/
        !            68: 
        !            69: #define STRING_BUF_COOKIE      0x3f8209ec
        !            70: 
        !            71: /* Internal state for a string_buf_output() stream */
        !            72: struct output_buf {
        !            73:        u_int32_t       cookie;                         /* sanity check id */
        !            74:        char            *buf;                           /* output buffer */
        !            75:        size_t          length;                         /* chars in buf */
        !            76:        size_t          alloc;                          /* amount allocated */
        !            77:        int             error;                          /* write error */
        !            78:        char            *mtype;                         /* memory type */
        !            79:        char            mtype_buf[TYPED_MEM_TYPELEN];
        !            80: };
        !            81: 
        !            82: /* Stream methods */
        !            83: static int     string_buf_output_write(void *arg, const char *data, int len);
        !            84: static int     string_buf_output_close(void *arg);
        !            85: 
        !            86: /*
        !            87:  * Create a new output string buffer stream.
        !            88:  */
        !            89: FILE *
        !            90: string_buf_output(const char *mtype)
        !            91: {
        !            92:        struct output_buf *sbuf;
        !            93:        int esave;
        !            94:        FILE *fp;
        !            95: 
        !            96:        if ((sbuf = MALLOC(mtype, sizeof(*sbuf))) == NULL)
        !            97:                return (NULL);
        !            98:        memset(sbuf, 0, sizeof(*sbuf));
        !            99:        sbuf->cookie = STRING_BUF_COOKIE;
        !           100:        if (mtype != NULL) {
        !           101:                strlcpy(sbuf->mtype_buf, mtype, sizeof(sbuf->mtype_buf));
        !           102:                sbuf->mtype = sbuf->mtype_buf;
        !           103:        }
        !           104:        if ((fp = funopen(sbuf, NULL, string_buf_output_write,
        !           105:            NULL, string_buf_output_close)) == NULL) {
        !           106:                esave = errno;
        !           107:                FREE(mtype, sbuf);
        !           108:                errno = esave;
        !           109:                return (NULL);
        !           110:        }
        !           111:        return (fp);
        !           112: }
        !           113: 
        !           114: /*
        !           115:  * Get current buffer contents.
        !           116:  */
        !           117: char *
        !           118: string_buf_content(FILE *fp, int reset)
        !           119: {
        !           120:        struct output_buf *const sbuf = GET_COOKIE(fp);
        !           121:        char *s;
        !           122: 
        !           123:        /* Sanity check */
        !           124:        assert((size_t)sbuf >= 2048 && sbuf->cookie == STRING_BUF_COOKIE);
        !           125: 
        !           126:        /* Check for previous error */
        !           127:        if (sbuf->error != 0) {
        !           128:                errno = sbuf->error;
        !           129:                return (NULL);
        !           130:        }
        !           131: 
        !           132:        /* Flush all output to buffer */
        !           133:        fflush(fp);
        !           134: 
        !           135:        /* If no data, initialize with empty string */
        !           136:        if ((s = sbuf->buf) == NULL) {
        !           137:                if (string_buf_output_write(sbuf, NULL, 0) == -1)
        !           138:                        return (NULL);
        !           139:                s = sbuf->buf;
        !           140:        }
        !           141: 
        !           142:        /* Reset buffer if desired */
        !           143:        if (reset) {
        !           144:                sbuf->buf = NULL;
        !           145:                sbuf->length = 0;
        !           146:                sbuf->alloc = 0;
        !           147:        }
        !           148: 
        !           149:        /* Done */
        !           150:        return (s);
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Get length of buffer.
        !           155:  */
        !           156: int
        !           157: string_buf_length(FILE *fp)
        !           158: {
        !           159:        struct output_buf *const sbuf = GET_COOKIE(fp);
        !           160: 
        !           161:        /* Sanity check */
        !           162:        assert((size_t)sbuf >= 2048 && sbuf->cookie == STRING_BUF_COOKIE);
        !           163: 
        !           164:        /* Flush output */
        !           165:        fflush(fp);
        !           166: 
        !           167:        /* Return length of current buffer */
        !           168:        return (sbuf->length);
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * Output stream write function.
        !           173:  */
        !           174: static int
        !           175: string_buf_output_write(void *arg, const char *data, int len)
        !           176: {
        !           177:        struct output_buf *const sbuf = arg;
        !           178:        int esave;
        !           179: 
        !           180:        /* Was there a previous error? */
        !           181:        if (sbuf->error) {
        !           182:                errno = sbuf->error;
        !           183:                return (-1);
        !           184:        }
        !           185: 
        !           186:        /* Expand buffer */
        !           187:        if (sbuf->length + len + 1 > sbuf->alloc) {
        !           188:                const size_t new_size = ROUNDUP2(sbuf->length + len + 1, 256);
        !           189:                void *mem;
        !           190: 
        !           191:                if ((mem = REALLOC(sbuf->mtype, sbuf->buf, new_size)) == NULL) {
        !           192:                        esave = errno;
        !           193:                        FREE(sbuf->mtype, sbuf->buf);
        !           194:                        sbuf->buf = NULL;
        !           195:                        sbuf->length = 0;
        !           196:                        sbuf->alloc = 0;
        !           197:                        sbuf->error = errno = esave;
        !           198:                        return (-1);
        !           199:                }
        !           200:                sbuf->buf = mem;
        !           201:                sbuf->alloc = new_size;
        !           202:        }
        !           203: 
        !           204:        /* Done */
        !           205:        memcpy(sbuf->buf + sbuf->length, data, len);
        !           206:        sbuf->length += len;
        !           207:        sbuf->buf[sbuf->length] = '\0';
        !           208:        return (len);
        !           209: }
        !           210: 
        !           211: /*
        !           212:  * Output stream close function.
        !           213:  */
        !           214: static int
        !           215: string_buf_output_close(void *arg)
        !           216: {
        !           217:        struct output_buf *const sbuf = arg;
        !           218: 
        !           219:        sbuf->error = EINVAL;
        !           220:        FREE(sbuf->mtype, sbuf->buf);
        !           221:        FREE(sbuf->mtype, sbuf);
        !           222:        return (0);
        !           223: }
        !           224: 
        !           225: /***********************************************************************
        !           226:                    STRING BUFFER INPUT STREAMS
        !           227: ***********************************************************************/
        !           228: 
        !           229: /* Internally used memory type for input streams */
        !           230: #define INPUT_MEM_TYPE         "string_buf_input"
        !           231: 
        !           232: /* Internal state for a string_buf_input() stream */
        !           233: struct input_buf {
        !           234:        char            *data;                          /* input data */
        !           235:        int             copied;                         /* data was copied */
        !           236: #ifndef __linux__
        !           237:        fpos_t          len;                            /* input length */
        !           238:        fpos_t          pos;                            /* read position */
        !           239: #else
        !           240:        _IO_off64_t     len;                            /* input length */
        !           241:        _IO_off64_t     pos;                            /* read position */
        !           242: #endif
        !           243: };
        !           244: 
        !           245: /* Stream methods */
        !           246: static int     string_buf_input_read(void *cookie, char *buf, int len);
        !           247: #ifndef __linux__
        !           248: static fpos_t  string_buf_input_seek(void *cookie, fpos_t pos, int whence);
        !           249: #else
        !           250: static int     string_buf_input_seek(void *cookie,
        !           251:                        _IO_off64_t *posp, int whence);
        !           252: #endif
        !           253: static int     string_buf_input_close(void *arg);
        !           254: 
        !           255: /*
        !           256:  * Create a new input string buffer stream.
        !           257:  */
        !           258: FILE *
        !           259: string_buf_input(const void *buf, size_t len, int copy)
        !           260: {
        !           261:        struct input_buf *r;
        !           262:        int esave;
        !           263:        FILE *fp;
        !           264: 
        !           265:        if ((r = MALLOC(INPUT_MEM_TYPE, sizeof(*r))) == NULL)
        !           266:                return (NULL);
        !           267:        memset(r, 0, sizeof(*r));
        !           268:        if (copy) {
        !           269:                if ((r->data = MALLOC(INPUT_MEM_TYPE, len)) == NULL) {
        !           270:                        FREE(INPUT_MEM_TYPE, r);
        !           271:                        return (NULL);
        !           272:                }
        !           273:                memcpy(r->data, buf, len);
        !           274:                r->copied = 1;
        !           275:        } else
        !           276:                r->data = (char *)buf;
        !           277:        r->pos = 0;
        !           278:        r->len = len;
        !           279:        if ((fp = funopen(r, string_buf_input_read,
        !           280:            NULL, string_buf_input_seek, string_buf_input_close)) == NULL) {
        !           281:                esave = errno;
        !           282:                if (r->copied)
        !           283:                        FREE(INPUT_MEM_TYPE, r->data);
        !           284:                FREE(INPUT_MEM_TYPE, r);
        !           285:                errno = esave;
        !           286:        }
        !           287:        return (fp);
        !           288: }
        !           289: 
        !           290: /*
        !           291:  * Seeker for input streams.
        !           292:  */
        !           293: #ifndef __linux__
        !           294: static fpos_t
        !           295: string_buf_input_seek(void *cookie, fpos_t pos, int whence)
        !           296: {
        !           297:        struct input_buf *const r = cookie;
        !           298: 
        !           299:        switch (whence) {
        !           300:        case SEEK_SET:
        !           301:                break;
        !           302:        case SEEK_CUR:
        !           303:                pos += r->pos;
        !           304:                break;
        !           305:        case SEEK_END:
        !           306:                pos += r->len;
        !           307:                break;
        !           308:        default:
        !           309:                errno = EINVAL;
        !           310:                return (-1);
        !           311:        }
        !           312:        if (pos < 0) {
        !           313:                errno = EINVAL;
        !           314:                return (-1);
        !           315:        }
        !           316:        if (pos > r->len) {
        !           317:                errno = EINVAL;
        !           318:                return (-1);
        !           319:        }
        !           320:        r->pos = pos;
        !           321:        return (pos);
        !           322: }
        !           323: #else
        !           324: static int
        !           325: string_buf_input_seek(void *cookie, _IO_off64_t *posp, int whence)
        !           326: {
        !           327:        struct input_buf *const r = cookie;
        !           328:        _IO_off64_t newpos = *posp;
        !           329: 
        !           330:        switch (whence) {
        !           331:        case SEEK_SET:
        !           332:                break;
        !           333:        case SEEK_CUR:
        !           334:                newpos += r->pos;
        !           335:                break;
        !           336:        case SEEK_END:
        !           337:                newpos += r->len;
        !           338:                break;
        !           339:        default:
        !           340:                errno = EINVAL;
        !           341:                return (-1);
        !           342:        }
        !           343:        if (newpos < 0) {
        !           344:                errno = EINVAL;
        !           345:                return (-1);
        !           346:        }
        !           347:        if (newpos > r->len) {
        !           348:                errno = EINVAL;
        !           349:                return (-1);
        !           350:        }
        !           351:        *posp = r->pos = newpos;
        !           352:        return (0);
        !           353: }
        !           354: #endif
        !           355: 
        !           356: /*
        !           357:  * Reader for input streams.
        !           358:  */
        !           359: static int
        !           360: string_buf_input_read(void *cookie, char *buf, int len)
        !           361: {
        !           362:        struct input_buf *const r = cookie;
        !           363: 
        !           364:        if (len > r->len - r->pos)
        !           365:                len = r->len - r->pos;
        !           366:        memcpy(buf, r->data + r->pos, len);
        !           367:        r->pos += len;
        !           368:        return (len);
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Closer for input streams.
        !           373:  */
        !           374: static int
        !           375: string_buf_input_close(void *cookie)
        !           376: {
        !           377:        struct input_buf *const r = cookie;
        !           378: 
        !           379:        if (r->copied)
        !           380:                FREE(INPUT_MEM_TYPE, r->data);
        !           381:        FREE(INPUT_MEM_TYPE, r);
        !           382:        return (0);
        !           383: }
        !           384: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>