• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
30 struct 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  */
expandBufAlloc()41 ExpandBuf* 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  */
expandBufFree(ExpandBuf * pBuf)56 void 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  */
expandBufGetBuffer(ExpandBuf * pBuf)68 u1* expandBufGetBuffer(ExpandBuf* pBuf)
69 {
70     return pBuf->storage;
71 }
72 
73 /*
74  * Get the amount of data currently in the buffer.
75  */
expandBufGetLength(ExpandBuf * pBuf)76 size_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  */
ensureSpace(ExpandBuf * pBuf,int newCount)86 static 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         ALOGE("realloc(%d) failed", pBuf->maxLen);
99         abort();
100     }
101 
102     pBuf->storage = newPtr;
103 }
104 
105 /*
106  * Allocate some space in the buffer.
107  */
expandBufAddSpace(ExpandBuf * pBuf,int gapSize)108 u1* 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  */
expandBufAdd1(ExpandBuf * pBuf,u1 val)123 void 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  */
expandBufAdd2BE(ExpandBuf * pBuf,u2 val)133 void 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  */
expandBufAdd4BE(ExpandBuf * pBuf,u4 val)143 void 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  */
expandBufAdd8BE(ExpandBuf * pBuf,u8 val)153 void 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  */
expandBufAddUtf8String(ExpandBuf * pBuf,const u1 * str)168 void 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