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 }