#include <iostream>
#include <kitchen/type.h>
namespace kc {
class buffer {
private:
buffer(const buffer& other ); // non construction-copyable
buffer& operator=( const buffer& ); // non copyable
protected:
uint8 *_buffer;
uint32 _valid;
uint32 _size; // Size of the buffer
uint32 _index; // Index into the buffer.
public:
explicit buffer(); // In concordance with this, and the private directions, a buffer object becomes un-copyable
explicit buffer(uint32 size); // Initialize with a size. But no buffer foo = 1024!
// These are explicit so that someone can't do, say, buffer foo = 1024. We don't want to convert from an int to a buffer! That wouldn't make sense!
~buffer(); // Delete the buffer!
uint8* operator*() { return _buffer; } // Returns a pointer to the buffer...just like a pointer! Returns a NULL pointer if the buffer is not valid!!
uint8* operator+(const int offset) { return (_buffer + offset); } // For pointer arithmetic i.e. *(object + 4). This had bounds checking (and returning of NULL) but it got way, WAY TOO SLOW.
operator bool() { return (_valid ? true : false); } // Tests if we are valid or not
operator void*() { return (void *)_buffer; }
operator char*() { return (char *)_buffer; } // Cast this to a uint8*
operator uint8*() { return _buffer; }
operator uint32*() { return (uint32 *)_buffer; }
operator uint64*() { return (uint64 *)_buffer; }
uint8 &operator[](int offset) { if (!_valid) { return _buffer[0]; } if (((uint32)offset < _size) && (offset >= 0)) return _buffer[offset]; else { _valid = 0; return _buffer[0]; } } // De-referencing like a pointer
uint32 operator=(uint32 what) { if (!_valid) return 0; if (what > _size) { _valid = 0; return 0; } _index = what; return what; } // Sets the index...has a return to do a = b = c =...
friend std::ostream& operator<<(std::ostream& os, const buffer& me) { if (!me._valid) { os << "INVALID BUFFER"; } else { os << me._buffer; } return os; } // Print us to an ostream...usually cout.
uint32 allocate(uint32 size); // Deletes and allocates new buffer
uint32 reallocate(uint32 size); // realloc()'s the buffer
void destroy(); // Destroys the buffer
uint32 is_valid() { return _valid; }
uint32 is_full() { if (!_valid) return 0; return ((_index < _size) ? 0 : 1); }
uint32 size() { return _size; }
uint32 bytes_left() { if (!_valid) return 0; return (_size - _index); }
uint8 *start_ptr() { if (!_valid) return NULL; return _buffer; }
uint8 *index_ptr() { if (!_valid) return NULL; return (_buffer + _index); }
uint32 index() { return _index; }
uint32 wrote(uint32 length) { if ((!_valid) || (length == 0)) { return 0; } if ((length + _index) <= _size) { _index += length; return 1; } else { _valid = 0; return 0; } } // Let the class know that we wrote to the buffer
uint32 seek(uint32 whereto) { if (!_valid) { return 0; } if (whereto >= _size) { _valid = 0; return 0; } _index = whereto; return 1; }
void force_valid() { _valid = 1; } // Only do this after an unsuccesful copy_into!
uint32 copy_into(uint8 *src, const uint32 length); // Copies into the buffer and returns 0 on success
uint32 copy_into(void *src, const uint32 length); // Copies into the buffer and returns 0 on success
uint32 copy_into(buffer& src, const uint32 length); // Copies into another buffer object
// Just a few for the easyness
uint32 copy_into(uint32 src);
uint32 copy_into(uint64 src);
uint32 copy_into(std::string& src);
uint32 copy_available_into(void *src, const uint32 length);// Copies into the buffer and returns the number of bytes written
uint32 copy_available_into(uint8 *src, const uint32 length);// Copies into the buffer and returns the number of bytes written
uint32 copy_available_into(buffer& src, const uint32 length); // Copies from another buffer object
uint32 copy_to(uint8 *dest, const uint32 length); // Copies from the buffer
uint32 copy_to(void *dest, const uint32 length); // Copies
uint32 copy_to(uint32 &dest);
uint32 copy_to(uint64 &dest);
uint32 copy_available_to(uint8 *dest, const uint32 length);
uint32 copy_available_to(void *dest, const uint32 length);
void erase() { _index = 0; } // "erases" the buffer. Note that this is different from zeroing it!
};
}