Add circular buffer to coral library
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							parent
							
								
									37b2586eaa
								
							
						
					
					
						commit
						cea0a4e0ed
					
				
							
								
								
									
										115
									
								
								source/coral.cpp
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								source/coral.cpp
									
									
									
									
									
								
							@ -452,12 +452,34 @@ export namespace coral {
 | 
			
		||||
		unavailable,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Readable resource interface.
 | 
			
		||||
	 */
 | 
			
		||||
	struct reader {
 | 
			
		||||
		virtual expected<usize, io_error> read(slice<u8> const & buffer) = 0;
 | 
			
		||||
		virtual ~reader() {}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Attempts to fill `data` with whatever data the reader has to offer, returning the number
 | 
			
		||||
		 * of bytes actually read.
 | 
			
		||||
		 *
 | 
			
		||||
		 * Should the read operation fail for any reason, a [io_error] is returned instead.
 | 
			
		||||
		 */
 | 
			
		||||
		virtual expected<usize, io_error> read(slice<u8> const & data) = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Writable resource interface.
 | 
			
		||||
	 */
 | 
			
		||||
	struct writer {
 | 
			
		||||
		virtual expected<usize, io_error> write(slice<u8 const> const & buffer) = 0;
 | 
			
		||||
		virtual ~writer() {}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Attempts to write `data` out to the writer, returning the number of bytes actually
 | 
			
		||||
		 * written.
 | 
			
		||||
		 *
 | 
			
		||||
		 * Should the write operation fail for any reason, a [io_error] is returned instead.
 | 
			
		||||
		 */
 | 
			
		||||
		virtual expected<usize, io_error> write(slice<u8 const> const & data) = 0;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -617,4 +639,93 @@ export namespace coral {
 | 
			
		||||
 | 
			
		||||
		return a;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Multiplexing byte buffer of `capacity` size that may be used for memory-backed I/O
 | 
			
		||||
	 * operations and lightweight data construction.
 | 
			
		||||
	 */
 | 
			
		||||
	template<usize capacity> struct ring_buffer : public writer, public reader {
 | 
			
		||||
		ring_buffer(coral::u8 fill_value) : data{fill_value} {}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Returns the base pointer of the buffer data.
 | 
			
		||||
		 */
 | 
			
		||||
		u8 * begin() {
 | 
			
		||||
			return this->data;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Returns the base pointer of the buffer data.
 | 
			
		||||
		 */
 | 
			
		||||
		u8 const * begin() const {
 | 
			
		||||
			return this->data;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Returns the tail pointer of the buffer data.
 | 
			
		||||
		 */
 | 
			
		||||
		u8 * end() {
 | 
			
		||||
			return this->data + this->cursor;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Returns the tail pointer of the buffer data.
 | 
			
		||||
		 */
 | 
			
		||||
		u8 const * end() const {
 | 
			
		||||
			return this->data + this->cursor;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Returns `true` if the buffer has been completely filled with data.
 | 
			
		||||
		 */
 | 
			
		||||
		bool is_full() const {
 | 
			
		||||
			return this->filled == capacity;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Reads whatever data is in the buffer into `data`, returning the number of bytes read
 | 
			
		||||
		 * from the buffer.
 | 
			
		||||
		 */
 | 
			
		||||
		expected<usize, io_error> read(slice<u8> const & data) override {
 | 
			
		||||
			slice const readable_data{this->data, min(this->filled, data.length)};
 | 
			
		||||
 | 
			
		||||
			this->filled -= readable_data.length;
 | 
			
		||||
 | 
			
		||||
			for (usize index = 0; index < readable_data.length; index += 1) {
 | 
			
		||||
				data[index] = this->data[this->read_index];
 | 
			
		||||
				this->read_index = (this->read_index + 1) % capacity;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return readable_data.length;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Attempts to write `data` to the buffer, returning the number of bytes written or
 | 
			
		||||
		 * [io_error::unavailable] if it has been completely filled and no more bytes can be
 | 
			
		||||
		 * written.
 | 
			
		||||
		 */
 | 
			
		||||
		expected<usize, io_error> write(slice<u8 const> const & data) override {
 | 
			
		||||
			if (this->is_full()) return io_error::unavailable;
 | 
			
		||||
 | 
			
		||||
			slice const writable_data{data.sliced(0, min(data.length, this->filled))};
 | 
			
		||||
 | 
			
		||||
			this->filled += writable_data.length;
 | 
			
		||||
 | 
			
		||||
			for (usize index = 0; index < writable_data.length; index += 1) {
 | 
			
		||||
				this->data[this->write_index] = data[index];
 | 
			
		||||
				this->write_index = (this->write_index + 1) % capacity;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return writable_data.length;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
		usize filled = 0;
 | 
			
		||||
 | 
			
		||||
		usize read_index = 0;
 | 
			
		||||
 | 
			
		||||
		usize write_index = 0;
 | 
			
		||||
 | 
			
		||||
		u8 data[capacity];
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user