Home | History | Annotate | Download | only in jdwp
      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