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
35static byte dummy[1 << 10];
36
37bool bytes::inBounds(const void* p) {
38 return p >= ptr && p < limit();
39}
40
41void 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
51void 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
72void 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
82int bytes::indexOf(byte c) {
83 byte* p = (byte*) memchr(ptr, c, len);
84 return (p == 0) ? -1 : (int)(p - ptr);
85}
86
87byte* bytes::writeTo(byte* bp) {
88 memcpy(bp, ptr, len);
89 return bp+len;
90}
91
92int 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
100void 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
111void 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
119const 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.
130byte* 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
160void 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
167int 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
175void 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
187int 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