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