ExpandBuf.cpp revision 60fc806b679a3655c228b4093058c59941a49cfe
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * Implementation of an expandable byte buffer.  Designed for serializing
18 * primitive values, e.g. JDWP replies.
19 */
20#include "jdwp/ExpandBuf.h"
21#include "Bits.h"
22#include "Common.h"
23
24#include <stdlib.h>
25#include <string.h>
26
27/*
28 * Data structure used to track buffer use.
29 */
30struct ExpandBuf {
31    u1*     storage;
32    int     curLen;
33    int     maxLen;
34};
35
36#define kInitialStorage 64
37
38/*
39 * Allocate a JdwpBuf and some initial storage.
40 */
41ExpandBuf* expandBufAlloc()
42{
43    ExpandBuf* newBuf;
44
45    newBuf = (ExpandBuf*) malloc(sizeof(*newBuf));
46    newBuf->storage = (u1*) malloc(kInitialStorage);
47    newBuf->curLen = 0;
48    newBuf->maxLen = kInitialStorage;
49
50    return newBuf;
51}
52
53/*
54 * Free a JdwpBuf and associated storage.
55 */
56void expandBufFree(ExpandBuf* pBuf)
57{
58    if (pBuf == NULL)
59        return;
60
61    free(pBuf->storage);
62    free(pBuf);
63}
64
65/*
66 * Get a pointer to the start of the buffer.
67 */
68u1* expandBufGetBuffer(ExpandBuf* pBuf)
69{
70    return pBuf->storage;
71}
72
73/*
74 * Get the amount of data currently in the buffer.
75 */
76size_t expandBufGetLength(ExpandBuf* pBuf)
77{
78    return pBuf->curLen;
79}
80
81
82/*
83 * Ensure that the buffer has enough space to hold incoming data.  If it
84 * doesn't, resize the buffer.
85 */
86static void ensureSpace(ExpandBuf* pBuf, int newCount)
87{
88    u1* newPtr;
89
90    if (pBuf->curLen + newCount <= pBuf->maxLen)
91        return;
92
93    while (pBuf->curLen + newCount > pBuf->maxLen)
94        pBuf->maxLen *= 2;
95
96    newPtr = (u1*) realloc(pBuf->storage, pBuf->maxLen);
97    if (newPtr == NULL) {
98        LOGE("realloc(%d) failed", pBuf->maxLen);
99        abort();
100    }
101
102    pBuf->storage = newPtr;
103}
104
105/*
106 * Allocate some space in the buffer.
107 */
108u1* expandBufAddSpace(ExpandBuf* pBuf, int gapSize)
109{
110    u1* gapStart;
111
112    ensureSpace(pBuf, gapSize);
113    gapStart = pBuf->storage + pBuf->curLen;
114    /* do we want to garbage-fill the gap for debugging? */
115    pBuf->curLen += gapSize;
116
117    return gapStart;
118}
119
120/*
121 * Append a byte.
122 */
123void expandBufAdd1(ExpandBuf* pBuf, u1 val)
124{
125    ensureSpace(pBuf, sizeof(val));
126    *(pBuf->storage + pBuf->curLen) = val;
127    pBuf->curLen++;
128}
129
130/*
131 * Append two big-endian bytes.
132 */
133void expandBufAdd2BE(ExpandBuf* pBuf, u2 val)
134{
135    ensureSpace(pBuf, sizeof(val));
136    set2BE(pBuf->storage + pBuf->curLen, val);
137    pBuf->curLen += sizeof(val);
138}
139
140/*
141 * Append four big-endian bytes.
142 */
143void expandBufAdd4BE(ExpandBuf* pBuf, u4 val)
144{
145    ensureSpace(pBuf, sizeof(val));
146    set4BE(pBuf->storage + pBuf->curLen, val);
147    pBuf->curLen += sizeof(val);
148}
149
150/*
151 * Append eight big-endian bytes.
152 */
153void expandBufAdd8BE(ExpandBuf* pBuf, u8 val)
154{
155    ensureSpace(pBuf, sizeof(val));
156    set8BE(pBuf->storage + pBuf->curLen, val);
157    pBuf->curLen += sizeof(val);
158}
159
160/*
161 * Add a UTF8 string as a 4-byte length followed by a non-NULL-terminated
162 * string.
163 *
164 * Because these strings are coming out of the VM, it's safe to assume that
165 * they can be null-terminated (either they don't have null bytes or they
166 * have stored null bytes in a multi-byte encoding).
167 */
168void expandBufAddUtf8String(ExpandBuf* pBuf, const u1* str)
169{
170    int strLen = strlen((const char*)str);
171
172    ensureSpace(pBuf, sizeof(u4) + strLen);
173    setUtf8String(pBuf->storage + pBuf->curLen, str);
174    pBuf->curLen += sizeof(u4) + strLen;
175}
176