| /* |
| * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "defines.h" |
| #include "bytes.h" |
| #include "utils.h" |
| |
| |
| static byte dummy[1 << 10]; |
| |
| bool bytes::inBounds(const void* p) { |
| return p >= ptr && p < limit(); |
| } |
| |
| void bytes::malloc(size_t len_) { |
| len = len_; |
| ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always |
| if (ptr == null) { |
| // set ptr to some victim memory, to ease escape |
| set(dummy, sizeof(dummy)-1); |
| unpack_abort(ERROR_ENOMEM); |
| } |
| } |
| |
| void bytes::realloc(size_t len_) { |
| if (len == len_) return; // nothing to do |
| if (ptr == dummy) return; // escaping from an error |
| if (ptr == null) { |
| malloc(len_); |
| return; |
| } |
| byte* oldptr = ptr; |
| ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, add_size(len_, 1)); |
| if (ptr != null) { |
| mtrace('r', oldptr, 0); |
| mtrace('m', ptr, len_+1); |
| if (len < len_) memset(ptr+len, 0, len_-len); |
| ptr[len_] = 0; |
| len = len_; |
| } else { |
| ptr = oldptr; // ease our escape |
| unpack_abort(ERROR_ENOMEM); |
| } |
| } |
| |
| void bytes::free() { |
| if (ptr == dummy) return; // escaping from an error |
| if (ptr != null) { |
| mtrace('f', ptr, 0); |
| ::free(ptr); |
| } |
| len = 0; |
| ptr = 0; |
| } |
| |
| int bytes::indexOf(byte c) { |
| byte* p = (byte*) memchr(ptr, c, len); |
| return (p == 0) ? -1 : (int)(p - ptr); |
| } |
| |
| byte* bytes::writeTo(byte* bp) { |
| memcpy(bp, ptr, len); |
| return bp+len; |
| } |
| |
| int bytes::compareTo(bytes& other) { |
| size_t l1 = len; |
| size_t l2 = other.len; |
| int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2); |
| if (cmp != 0) return cmp; |
| return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0; |
| } |
| |
| void bytes::saveFrom(const void* ptr_, size_t len_) { |
| malloc(len_); |
| // Save as much as possible. (Helps unpacker::abort.) |
| if (len_ > len) { |
| assert(ptr == dummy); // error recovery |
| len_ = len; |
| } |
| copyFrom(ptr_, len_); |
| } |
| |
| //#TODO: Need to fix for exception handling |
| void bytes::copyFrom(const void* ptr_, size_t len_, size_t offset) { |
| assert(len_ == 0 || inBounds(ptr + offset)); |
| assert(len_ == 0 || inBounds(ptr + offset+len_-1)); |
| memcpy(ptr+offset, ptr_, len_); |
| } |
| |
| |
| #ifndef PRODUCT |
| const char* bytes::string() { |
| if (len == 0) return ""; |
| if (ptr[len] == 0 && strlen((char*)ptr) == len) return (const char*) ptr; |
| bytes junk; |
| junk.saveFrom(*this); |
| return (char*) junk.ptr; |
| } |
| #endif |
| |
| // Make sure there are 'o' bytes beyond the fill pointer, |
| // advance the fill pointer, and return the old fill pointer. |
| byte* fillbytes::grow(size_t s) { |
| size_t nlen = add_size(b.len, s); |
| if (nlen <= allocated) { |
| b.len = nlen; |
| return limit()-s; |
| } |
| size_t maxlen = nlen; |
| if (maxlen < 128) maxlen = 128; |
| if (maxlen < allocated*2) maxlen = allocated*2; |
| if (allocated == 0) { |
| // Initial buffer was not malloced. Do not reallocate it. |
| bytes old = b; |
| b.malloc(maxlen); |
| if (b.len == maxlen) |
| old.writeTo(b.ptr); |
| } else { |
| b.realloc(maxlen); |
| } |
| allocated = b.len; |
| if (allocated != maxlen) { |
| assert(unpack_aborting()); |
| b.len = nlen-s; // back up |
| return dummy; // scribble during error recov. |
| } |
| // after realloc, recompute pointers |
| b.len = nlen; |
| assert(b.len <= allocated); |
| return limit()-s; |
| } |
| |
| void fillbytes::ensureSize(size_t s) { |
| if (allocated >= s) return; |
| size_t len0 = b.len; |
| grow(s - size()); |
| b.len = len0; // put it back |
| } |
| |
| int ptrlist::indexOf(const void* x) { |
| int len = length(); |
| for (int i = 0; i < len; i++) { |
| if (get(i) == x) return i; |
| } |
| return -1; |
| } |
| |
| void ptrlist::freeAll() { |
| int len = length(); |
| for (int i = 0; i < len; i++) { |
| void* p = (void*) get(i); |
| if (p != null) { |
| mtrace('f', p, 0); |
| ::free(p); |
| } |
| } |
| free(); |
| } |
| |
| int intlist::indexOf(int x) { |
| int len = length(); |
| for (int i = 0; i < len; i++) { |
| if (get(i) == x) return i; |
| } |
| return -1; |
| } |