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 */ 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 */ 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 */ 68 u1* expandBufGetBuffer(ExpandBuf* pBuf) 69 { 70 return pBuf->storage; 71 } 72 73 /* 74 * Get the amount of data currently in the buffer. 75 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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