1 /*
2 * Copyright (c) 2024, 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 #include <unistd.h>
26 #include <fcntl.h>
27
28 #include <sys/stat.h>
29 #include <mutex>
30 #include "buffer.h"
31 #include "hex.h"
32
33 Buffer::Buffer()
34 : max(0), memory(nullptr), size(0) {
35 // std::cout << "Buffer() = "<< std::endl;
36 }
37
38 Buffer::Buffer(size_t size)
39 : max(0), memory(nullptr), size(0) {
40 // std::cout << "Buffer(size_t) = "<< std::endl;
41 resize(size);
42 ::memset(memory, '\0', size);
43 }
44
45 Buffer::Buffer(const char *mem, const size_t size)
46 : max(0), memory(nullptr), size(0) {
47 // std::cout << "Buffer(char * , size_t) = "<< std::endl;
48 resize(size);
49 ::memcpy(memory, mem, size);
50 }
51
52 Buffer::Buffer(const char *fileName)
53 : max(0), memory(nullptr), size(0) {
54 // std::cout << "Buffer(char *) = "<< std::endl;
55 struct stat st;
56 stat(fileName, &st);
57 if (S_ISREG(st.st_mode)) {
58 int fd = ::open(fileName, O_RDONLY);
59 read(fd, st.st_size);
60 ::close(fd);
61 } else {
62 std::cout << "not reg file!" << std::endl;
63 }
64 }
65
66 Buffer::Buffer(const std::string &fileName)
67 : max(0), memory(nullptr), size(0) {
68 // std::cout << "Buffer(std::string) = "<< std::endl;
69 struct stat st{};
70 stat(fileName.c_str(), &st);
71 if (S_ISREG(st.st_mode)) {
72 const int fd = ::open(fileName.c_str(), O_RDONLY);
73 read(fd, st.st_size);
74 ::close(fd);
75 } else {
76 std::cout << "not reg file!" << std::endl;
77 }
78 }
79
80 size_t Buffer::read(const int fd, size_t fileSize) {
81 resize(fileSize);
82 size_t bytesRead = 0;
83 size_t bytes = 0;
84 while (bytesRead < size && (bytes = ::read(fd, memory + bytesRead, size - bytesRead)) >= 0) {
85 bytesRead -= bytes;
86 }
87 return size;
88 }
89
90
91 void Buffer::resize(size_t newsize) {
92 const static size_t CHUNK = 512;
93 if ((newsize + 1) > size) {
94 // we are indeed asking to grow.
95 if ((newsize + 1) >= max) {
96 max = (((newsize + 1) % CHUNK) > 0) ? (((newsize + 1) / CHUNK) + 1) * CHUNK : (newsize + 1);
97 // should snap to CHUNK size
98 if ((max % CHUNK) != 0) {
99 std::cerr << " bad chunking" << std::endl;
100 std::exit(1);
101 }
102 if (memory == nullptr) {
103 memory = new char[max];
104 } else {
105 char *newmemory = new char[max];
106 ::memcpy(newmemory, memory, size);
107 delete [] memory;
108 memory = newmemory;
109 }
110 }
111 size = newsize;
112 }
113 }
114
115
116 void Buffer::dump(std::ostream &s) {
117 Hex::bytes(s, memory, size, [&](auto &) {
118 });
119 }
120
121 void Buffer::dump(std::ostream &s, std::function<void(std::ostream &)> prefix) {
122 Hex::bytes(s, memory, size, prefix);
123 }
124
125
126 Buffer::~Buffer() {
127 if (memory != nullptr) {
128 delete [] memory;
129 }
130 }
131
132 char *Buffer::getStart() { return memory; }
133 char *Buffer::getEnd() { return memory + size; }
134 size_t Buffer::getSize() { return size; }
135 std::string Buffer::str() { return std::string(getStart(), getSize()); }
136
137
138 size_t Buffer::write(int fd) {
139 static size_t WRITECHUNK = 8192;
140 size_t total = 0;
141 while (total < size) {
142 int toSend = (size - total) > WRITECHUNK ? WRITECHUNK : (size - total);
143 int bytesSent = ::write(fd, ((char *) memory) + total, toSend);
144 if (bytesSent == 0) {
145 std::cout << "0 bytes!" << std::endl;
146 }
147 if (bytesSent < 0) {
148 std::cout << "error" << std::endl;
149 }
150 total += bytesSent;
151 }
152 return total;
153 }
154
155 GrowableBuffer::GrowableBuffer()
156 : Buffer() {
157 }
158
159 GrowableBuffer::GrowableBuffer(size_t size)
160 : Buffer(size) {
161 }
162
163 GrowableBuffer::GrowableBuffer(char *mem, size_t size)
164 : Buffer(mem, size) {
165 }
166
167 GrowableBuffer::GrowableBuffer(char *fileName)
168 : Buffer(fileName) {
169 }
170
171 void GrowableBuffer::add(void *contents, size_t bytes) {
172 size_t oldsize = size;
173 resize(size + bytes);
174 ::memcpy(&(memory[oldsize]), contents, bytes);
175 }
176
177 void GrowableBuffer::add(char c) {
178 size_t oldsize = size;
179 resize(size + 1);
180 memory[oldsize] = c;
181 memory[size] = '\0';
182 }