blob: 8f0e0419bc2152b777d158e534e5ce677f578d48 [file] [log] [blame]
/*
* 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;
}