1 /* 2 ============================================================================== 3 4 This file is part of the Water library. 5 Copyright (c) 2016 ROLI Ltd. 6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com> 7 8 Permission is granted to use this software under the terms of the ISC license 9 http://www.isc.org/downloads/software-support-policy/isc-license/ 10 11 Permission to use, copy, modify, and/or distribute this software for any 12 purpose with or without fee is hereby granted, provided that the above 13 copyright notice and this permission notice appear in all copies. 14 15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD 16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, 18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 21 OF THIS SOFTWARE. 22 23 ============================================================================== 24 */ 25 26 #ifndef WATER_MEMORYBLOCK_H_INCLUDED 27 #define WATER_MEMORYBLOCK_H_INCLUDED 28 29 #include "HeapBlock.h" 30 31 namespace water { 32 33 //============================================================================== 34 /** 35 A class to hold a resizable block of raw data. 36 37 */ 38 class MemoryBlock 39 { 40 public: 41 //============================================================================== 42 /** Create an uninitialised block with 0 size. */ 43 MemoryBlock() noexcept; 44 45 /** Creates a memory block with a given initial size. 46 47 @param initialSize the size of block to create 48 @param initialiseToZero whether to clear the memory or just leave it uninitialised 49 */ 50 MemoryBlock (const size_t initialSize, 51 bool initialiseToZero = false); 52 53 /** Creates a copy of another memory block. */ 54 MemoryBlock (const MemoryBlock&); 55 56 /** Creates a memory block using a copy of a block of data. 57 58 @param dataToInitialiseFrom some data to copy into this block 59 @param sizeInBytes how much space to use 60 */ 61 MemoryBlock (const void* dataToInitialiseFrom, size_t sizeInBytes); 62 63 /** Destructor. */ 64 ~MemoryBlock() noexcept; 65 66 /** Copies another memory block onto this one. 67 This block will be resized and copied to exactly match the other one. 68 */ 69 MemoryBlock& operator= (const MemoryBlock&); 70 71 #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS 72 MemoryBlock (MemoryBlock&&) noexcept; 73 MemoryBlock& operator= (MemoryBlock&&) noexcept; 74 #endif 75 76 //============================================================================== 77 /** Compares two memory blocks. 78 @returns true only if the two blocks are the same size and have identical contents. 79 */ 80 bool operator== (const MemoryBlock& other) const noexcept; 81 82 /** Compares two memory blocks. 83 @returns true if the two blocks are different sizes or have different contents. 84 */ 85 bool operator!= (const MemoryBlock& other) const noexcept; 86 87 /** Returns true if the data in this MemoryBlock matches the raw bytes passed-in. */ 88 bool matches (const void* data, size_t dataSize) const noexcept; 89 90 //============================================================================== 91 /** Returns a void pointer to the data. 92 93 Note that the pointer returned will probably become invalid when the 94 block is resized. 95 */ getData()96 void* getData() const noexcept { return data; } 97 98 /** Returns a byte from the memory block. 99 This returns a reference, so you can also use it to set a byte. 100 */ 101 template <typename Type> 102 char& operator[] (const Type offset) const noexcept { return data [offset]; } 103 104 105 //============================================================================== 106 /** Returns the block's current allocated size, in bytes. */ getSize()107 size_t getSize() const noexcept { return size; } 108 109 /** Resizes the memory block. 110 111 Any data that is present in both the old and new sizes will be retained. 112 When enlarging the block, the new space that is allocated at the end can either be 113 cleared, or left uninitialised. 114 115 @param newSize the new desired size for the block 116 @param initialiseNewSpaceToZero if the block gets enlarged, this determines 117 whether to clear the new section or just leave it 118 uninitialised 119 @see ensureSize 120 */ 121 void setSize (const size_t newSize, 122 bool initialiseNewSpaceToZero = false); 123 124 /** Increases the block's size only if it's smaller than a given size. 125 126 @param minimumSize if the block is already bigger than this size, no action 127 will be taken; otherwise it will be increased to this size 128 @param initialiseNewSpaceToZero if the block gets enlarged, this determines 129 whether to clear the new section or just leave it 130 uninitialised 131 @see setSize 132 */ 133 void ensureSize (const size_t minimumSize, 134 bool initialiseNewSpaceToZero = false); 135 136 /** Frees all the blocks data, setting its size to 0. */ 137 void reset(); 138 139 //============================================================================== 140 /** Fills the entire memory block with a repeated byte value. 141 This is handy for clearing a block of memory to zero. 142 */ 143 void fillWith (uint8 valueToUse) noexcept; 144 145 /** Adds another block of data to the end of this one. 146 The data pointer must not be null. This block's size will be increased accordingly. 147 */ 148 void append (const void* data, size_t numBytes); 149 150 /** Resizes this block to the given size and fills its contents from the supplied buffer. 151 The data pointer must not be null. 152 */ 153 void replaceWith (const void* data, size_t numBytes); 154 155 /** Inserts some data into the block. 156 The dataToInsert pointer must not be null. This block's size will be increased accordingly. 157 If the insert position lies outside the valid range of the block, it will be clipped to 158 within the range before being used. 159 */ 160 void insert (const void* dataToInsert, size_t numBytesToInsert, size_t insertPosition); 161 162 /** Chops out a section of the block. 163 164 This will remove a section of the memory block and close the gap around it, 165 shifting any subsequent data downwards and reducing the size of the block. 166 167 If the range specified goes beyond the size of the block, it will be clipped. 168 */ 169 void removeSection (size_t startByte, size_t numBytesToRemove); 170 171 //============================================================================== 172 /** Copies data into this MemoryBlock from a memory address. 173 174 @param srcData the memory location of the data to copy into this block 175 @param destinationOffset the offset in this block at which the data being copied should begin 176 @param numBytes how much to copy in (if this goes beyond the size of the memory block, 177 it will be clipped so not to do anything nasty) 178 */ 179 void copyFrom (const void* srcData, 180 int destinationOffset, 181 size_t numBytes) noexcept; 182 183 /** Copies data from this MemoryBlock to a memory address. 184 185 @param destData the memory location to write to 186 @param sourceOffset the offset within this block from which the copied data will be read 187 @param numBytes how much to copy (if this extends beyond the limits of the memory block, 188 zeros will be used for that portion of the data) 189 */ 190 void copyTo (void* destData, 191 int sourceOffset, 192 size_t numBytes) const noexcept; 193 194 //============================================================================== 195 /** Exchanges the contents of this and another memory block. 196 No actual copying is required for this, so it's very fast. 197 */ 198 void swapWith (MemoryBlock& other) noexcept; 199 200 //============================================================================== 201 /** Release this object's data ownership, returning the data pointer. */ 202 void* release () noexcept; 203 204 //============================================================================== 205 /** Attempts to parse the contents of the block as a zero-terminated UTF8 string. */ 206 String toString() const; 207 208 //============================================================================== 209 /** Parses a string of hexadecimal numbers and writes this data into the memory block. 210 211 The block will be resized to the number of valid bytes read from the string. 212 Non-hex characters in the string will be ignored. 213 214 @see String::toHexString() 215 */ 216 void loadFromHexString (StringRef sourceHexString); 217 218 //============================================================================== 219 /** Sets a number of bits in the memory block, treating it as a long binary sequence. */ 220 void setBitRange (size_t bitRangeStart, 221 size_t numBits, 222 int binaryNumberToApply) noexcept; 223 224 /** Reads a number of bits from the memory block, treating it as one long binary sequence */ 225 int getBitRange (size_t bitRangeStart, 226 size_t numBitsToRead) const noexcept; 227 228 private: 229 //============================================================================== 230 HeapBlock<char> data; 231 size_t size; 232 }; 233 234 } 235 236 #endif // WATER_MEMORYBLOCK_H_INCLUDED 237