| 1 | /* |
| 2 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Oracle designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Oracle in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 22 | * or visit www.oracle.com if you need additional information or have any |
| 23 | * questions. |
| 24 | */ |
| 25 | |
| 26 | |
| 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> |
| 29 | #include <string.h> |
| 30 | #include "defines.h" |
| 31 | #include "bytes.h" |
| 32 | #include "utils.h" |
| 33 | |
| 34 | |
| 35 | static byte dummy[1 << 10]; |
| 36 | |
| 37 | bool bytes::inBounds(const void* p) { |
| 38 | return p >= ptr && p < limit(); |
| 39 | } |
| 40 | |
| 41 | void bytes::malloc(size_t len_) { |
| 42 | len = len_; |
| 43 | ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always |
| 44 | if (ptr == null) { |
| 45 | // set ptr to some victim memory, to ease escape |
| 46 | set(dummy, sizeof(dummy)-1); |
| 47 | unpack_abort(ERROR_ENOMEM); |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | void bytes::realloc(size_t len_) { |
| 52 | if (len == len_) return; // nothing to do |
| 53 | if (ptr == dummy) return; // escaping from an error |
| 54 | if (ptr == null) { |
| 55 | malloc(len_); |
| 56 | return; |
| 57 | } |
| 58 | byte* oldptr = ptr; |
| 59 | ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, add_size(len_, 1)); |
| 60 | if (ptr != null) { |
| 61 | mtrace('r', oldptr, 0); |
| 62 | mtrace('m', ptr, len_+1); |
| 63 | if (len < len_) memset(ptr+len, 0, len_-len); |
| 64 | ptr[len_] = 0; |
| 65 | len = len_; |
| 66 | } else { |
| 67 | ptr = oldptr; // ease our escape |
| 68 | unpack_abort(ERROR_ENOMEM); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | void bytes::free() { |
| 73 | if (ptr == dummy) return; // escaping from an error |
| 74 | if (ptr != null) { |
| 75 | mtrace('f', ptr, 0); |
| 76 | ::free(ptr); |
| 77 | } |
| 78 | len = 0; |
| 79 | ptr = 0; |
| 80 | } |
| 81 | |
| 82 | int bytes::indexOf(byte c) { |
| 83 | byte* p = (byte*) memchr(ptr, c, len); |
| 84 | return (p == 0) ? -1 : (int)(p - ptr); |
| 85 | } |
| 86 | |
| 87 | byte* bytes::writeTo(byte* bp) { |
| 88 | memcpy(bp, ptr, len); |
| 89 | return bp+len; |
| 90 | } |
| 91 | |
| 92 | int bytes::compareTo(bytes& other) { |
| 93 | size_t l1 = len; |
| 94 | size_t l2 = other.len; |
| 95 | int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2); |
| 96 | if (cmp != 0) return cmp; |
| 97 | return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0; |
| 98 | } |
| 99 | |
| 100 | void bytes::saveFrom(const void* ptr_, size_t len_) { |
| 101 | malloc(len_); |
| 102 | // Save as much as possible. (Helps unpacker::abort.) |
| 103 | if (len_ > len) { |
| 104 | assert(ptr == dummy); // error recovery |
| 105 | len_ = len; |
| 106 | } |
| 107 | copyFrom(ptr_, len_); |
| 108 | } |
| 109 | |
| 110 | //#TODO: Need to fix for exception handling |
| 111 | void bytes::copyFrom(const void* ptr_, size_t len_, size_t offset) { |
| 112 | assert(len_ == 0 || inBounds(ptr + offset)); |
| 113 | assert(len_ == 0 || inBounds(ptr + offset+len_-1)); |
| 114 | memcpy(ptr+offset, ptr_, len_); |
| 115 | } |
| 116 | |
| 117 | |
| 118 | #ifndef PRODUCT |
| 119 | const char* bytes::string() { |
| 120 | if (len == 0) return "" ; |
| 121 | if (ptr[len] == 0 && strlen((char*)ptr) == len) return (const char*) ptr; |
| 122 | bytes junk; |
| 123 | junk.saveFrom(*this); |
| 124 | return (char*) junk.ptr; |
| 125 | } |
| 126 | #endif |
| 127 | |
| 128 | // Make sure there are 'o' bytes beyond the fill pointer, |
| 129 | // advance the fill pointer, and return the old fill pointer. |
| 130 | byte* fillbytes::grow(size_t s) { |
| 131 | size_t nlen = add_size(b.len, s); |
| 132 | if (nlen <= allocated) { |
| 133 | b.len = nlen; |
| 134 | return limit()-s; |
| 135 | } |
| 136 | size_t maxlen = nlen; |
| 137 | if (maxlen < 128) maxlen = 128; |
| 138 | if (maxlen < allocated*2) maxlen = allocated*2; |
| 139 | if (allocated == 0) { |
| 140 | // Initial buffer was not malloced. Do not reallocate it. |
| 141 | bytes old = b; |
| 142 | b.malloc(maxlen); |
| 143 | if (b.len == maxlen) |
| 144 | old.writeTo(b.ptr); |
| 145 | } else { |
| 146 | b.realloc(maxlen); |
| 147 | } |
| 148 | allocated = b.len; |
| 149 | if (allocated != maxlen) { |
| 150 | assert(unpack_aborting()); |
| 151 | b.len = nlen-s; // back up |
| 152 | return dummy; // scribble during error recov. |
| 153 | } |
| 154 | // after realloc, recompute pointers |
| 155 | b.len = nlen; |
| 156 | assert(b.len <= allocated); |
| 157 | return limit()-s; |
| 158 | } |
| 159 | |
| 160 | void fillbytes::ensureSize(size_t s) { |
| 161 | if (allocated >= s) return; |
| 162 | size_t len0 = b.len; |
| 163 | grow(s - size()); |
| 164 | b.len = len0; // put it back |
| 165 | } |
| 166 | |
| 167 | int ptrlist::indexOf(const void* x) { |
| 168 | int len = length(); |
| 169 | for (int i = 0; i < len; i++) { |
| 170 | if (get(i) == x) return i; |
| 171 | } |
| 172 | return -1; |
| 173 | } |
| 174 | |
| 175 | void ptrlist::freeAll() { |
| 176 | int len = length(); |
| 177 | for (int i = 0; i < len; i++) { |
| 178 | void* p = (void*) get(i); |
| 179 | if (p != null) { |
| 180 | mtrace('f', p, 0); |
| 181 | ::free(p); |
| 182 | } |
| 183 | } |
| 184 | free(); |
| 185 | } |
| 186 | |
| 187 | int intlist::indexOf(int x) { |
| 188 | int len = length(); |
| 189 | for (int i = 0; i < len; i++) { |
| 190 | if (get(i) == x) return i; |
| 191 | } |
| 192 | return -1; |
| 193 | } |
| 194 | |