aboutsummaryrefslogtreecommitdiff
path: root/src/stringstream.c
blob: 435393233c066aee8b495f9cfd206eb93be5d6c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "stringstream.h"

#include <assert.h>

static int StringStreamClose(Stream *base)
{
    StringStream *ss = (StringStream *) base;
    bdestroy(ss->buffer);
    ss->buffer = NULL;
    return 0;
}

static int64_t StringStreamRead(void *ptr, size_t size, Stream *stream)
{
    StringStream *ss = (StringStream *) stream;
    int64_t available = blength(ss->buffer) - ss->pos;
    void *bufptr;

    if (available <= 0)
    {
        return -1;
    }

    if (size > (size_t) available)
        size = available;

    /* Use a temp buffer pointer to make some warnings disappear when using
       GCC */
    bufptr = bdataofs(ss->buffer, ss->pos);
    memcpy(ptr, bufptr, size);

    ss->pos += size;

    return size;
}

static int64_t StringStreamWrite(const void *ptr, size_t size, Stream *stream)
{
    StringStream *ss = (StringStream *) stream;
    struct tagbstring buf;
    if (ss->buffer->mlen <= 0)
        return -1;
    btfromblk(buf, ptr, size);
    bsetstr(ss->buffer, ss->pos, &buf, '\0');
    ss->pos += size;
    return size;
}

int StringStreamSeek(Stream *base, int64_t offset, int whence)
{
    StringStream *ss = (StringStream *) base;
    int64_t newpos = 0;

    if (whence == SEEK_SET)
    {
        newpos = offset;
    }
    else if (whence == SEEK_CUR)
    {
        newpos = ss->pos + offset;
    }
    else if (whence == SEEK_END)
    {
        newpos = blength(ss->buffer) - offset;
    }
    else
    {
        return -1;
    }

    if (newpos > blength(ss->buffer))
        return -1;

    if (newpos < 0)
        return -1;

    ss->pos = newpos;

    return 0;
}

int64_t StringStreamTell(Stream *base)
{
    StringStream *ss = (StringStream *) base;
    return ss->pos;
}

static const StreamOps StringStreamOps =
{
    StringStreamRead,
    StringStreamWrite,
    StringStreamClose,
    StringStreamSeek,
    StringStreamTell
};

int StringStreamInit(StringStream *stream)
{
    assert(stream != NULL);
    memset(stream, 0, sizeof(*stream));
    stream->pos = 0;
    stream->buffer = bfromcstr("");
    stream->base.ops = &StringStreamOps;
    return 0;
}

int StringStreamInitFromBstring(StringStream *stream, bstring buffer)
{
    assert(stream != NULL);
    memset(stream, 0, sizeof(*stream));
    stream->pos = 0;
    stream->buffer = buffer;
    stream->base.ops = &StringStreamOps;
    return 0;
}