changing back to custom vector class

This commit is contained in:
Noel Berry 2020-10-24 17:34:20 -07:00
parent 088e3a9103
commit b5e2c53613
8 changed files with 462 additions and 479 deletions

View File

@ -35,7 +35,8 @@ add_library(blah
public/blah/input/virtual_button.h
public/blah/input/virtual_axis.cpp
public/blah/input/virtual_axis.h
public/blah/containers/vector.h
public/blah/containers/stackvector.h
public/blah/containers/str.cpp
public/blah/containers/str.h
@ -83,6 +84,7 @@ add_library(blah
public/blah/math/vec2.h
public/blah/math/vec4.h
public/blah/streams/endian.h
public/blah/streams/bufferstream.cpp
public/blah/streams/bufferstream.h
public/blah/streams/filestream.cpp
@ -99,7 +101,7 @@ add_library(blah
private/blah/internal/graphics_opengl.cpp
private/blah/internal/input.h
private/blah/internal/platform.h
private/blah/internal/platform_sdl2.cpp "public/blah/containers/vector.h")
private/blah/internal/platform_sdl2.cpp)
target_include_directories(blah
PUBLIC

View File

@ -49,4 +49,5 @@
#include <blah/streams/bufferstream.h>
#include <blah/streams/filestream.h>
#include <blah/streams/memorystream.h>
#include <blah/streams/stream.h>
#include <blah/streams/stream.h>
#include <blah/streams/endian.h>

View File

@ -1,317 +0,0 @@
#pragma once
#include <blah/log.h>
#include <type_traits>
#include <new>
#include <string.h>
namespace Blah
{
template<class T>
class List
{
private:
// internal list buffer
T* m_buffer;
// total elements
int m_count;
// total capacity
int m_capacity;
public:
List();
List(int capacity);
List(const List& src);
List(List&& src) noexcept;
~List();
List& operator=(const List& src);
List& operator=(List&& src) noexcept;
// reserves the given amount of capacity
void reserve(int new_capacity);
// adds an element to the list
void add(const T& item);
template<class ...Args>
void emplace(Args&&...args);
// moves an element into the list
void add(T&& item);
// expands the list by the given amount, and returns a pointer to the first element
T* expand(int amount = 1);
// returns a reference to the element at the given index
T& operator[](int index);
// returns a reference to the element at the given index
const T& operator[](int index) const;
// returns a pointer to the first element
T* begin() { return m_buffer; }
// returns a pointer to the first element
const T* begin() const { return m_buffer; }
// returns a pointer to the last element
T* end() { return m_buffer + m_count; }
// returns a pointer to the last element
const T* end() const { return m_buffer + m_count; }
// clears all elements
void clear();
// removes the element at the index
void remove_at(int index);
// checks whether the given value is in the List (uses == operator)
bool contains(const T& item) const;
// returns the index of the given value in the list (uses == operator, -1 if not in list)
int index_of(const T& item) const;
// pops the top element off the list
T pop();
// returns the total number of elements
int count() const { return m_count; }
// returns the internal buffer capacity of the list
int capacity() const { return m_capacity; }
// removes all elements and disposes the internal buffer
void dispose();
};
template<class T>
List<T>::List()
{
m_buffer = nullptr;
m_count = m_capacity = 0;
}
template<class T>
List<T>::List(int capacity)
{
m_buffer = nullptr;
m_count = m_capacity = capacity;
reserve(m_capacity);
}
template<class T>
List<T>::List(const List<T>& src)
{
m_buffer = (T*)(::operator new (sizeof(T) * src.m_capacity));
m_count = src.m_count;
m_capacity = src.m_capacity;
for (int n = 0; n < m_count; n++)
new (m_buffer + n) T(*(src.m_buffer + n));
}
template<class T>
List<T>::List(List<T>&& src) noexcept
{
m_buffer = src.m_buffer;
m_count = src.m_count;
m_capacity = src.m_capacity;
src.m_buffer = nullptr;
src.m_count = src.m_capacity = 0;
}
template<class T>
List<T>& List<T>::operator=(const List<T>& src)
{
clear();
if (m_capacity < src.m_count)
reserve(src.m_count);
m_count = src.m_count;
for (int n = 0; n < m_count; n++)
new (m_buffer + n) T(*(src.m_buffer + n));
return *this;
}
template<class T>
List<T>& List<T>::operator=(List<T>&& src) noexcept
{
dispose();
m_buffer = src.m_buffer;
m_count = src.m_count;
m_capacity = src.m_capacity;
src.m_buffer = nullptr;
src.m_count = src.m_capacity = 0;
return *this;
}
template<class T>
List<T>::~List()
{
dispose();
}
template<class T>
void List<T>::reserve(int new_capacity)
{
if (new_capacity >= m_capacity)
{
auto last_capacity = m_capacity;
if (m_capacity <= 0)
m_capacity = 8;
while (new_capacity >= m_capacity)
m_capacity = m_capacity * 2;
T* new_buffer = (T*)::operator new (sizeof(T) * m_capacity);
if (std::is_trivially_copyable<T>::value)
{
memcpy(new_buffer, m_buffer, sizeof(T) * m_count);
}
else
{
for (int n = 0; n < m_count; n++)
{
new (new_buffer + n) T(std::move(m_buffer[n]));
m_buffer[n].~T();
}
}
::operator delete (m_buffer, sizeof(T) * last_capacity);
m_buffer = new_buffer;
}
}
template<class T>
T* List<T>::expand(int amount)
{
reserve(m_count + amount);
for (int n = m_count; n < m_count + amount; n++)
new (m_buffer + n) T();
m_count += amount;
return (m_buffer + m_count - amount);
}
template<class T>
void List<T>::add(const T& item)
{
reserve(m_count + 1);
new (m_buffer + m_count) T(item);
m_count++;
}
template<class T>
template<class ...Args>
void List<T>::emplace(Args&&...args)
{
reserve(m_count + 1);
new (m_buffer + m_count) T(args);
m_count++;
}
template<class T>
void List<T>::add(T&& item)
{
reserve(m_count + 1);
new (m_buffer + m_count) T(std::move(item));
m_count++;
}
template<class T>
T& List<T>::operator[](int index)
{
BLAH_ASSERT(index >= 0 && index < m_count, "Index is out of range");
return m_buffer[index];
}
template<class T>
const T& List<T>::operator[](int index) const
{
BLAH_ASSERT(index >= 0 && index < m_count, "Index is out of range");
return m_buffer[index];
}
template<class T>
void List<T>::clear()
{
for (T* it = m_buffer; it < m_buffer + m_count; it++)
it->~T();
m_count = 0;
}
template<class T>
void List<T>::remove_at(int index)
{
BLAH_ASSERT(index >= 0 && index < m_count, "Index is out of range");
m_buffer[index].~T();
if (index < m_count - 1)
{
int diff = (m_count - index - 1);
if (diff <= 0)
diff = 0;
if (std::is_trivially_copyable<T>::value)
{
memmove(m_buffer + index, m_buffer + index + 1, (size_t)diff * sizeof(T));
}
else
{
for (int i = index; i < m_count - 1; i++)
m_buffer[i] = std::move(m_buffer[i + 1]);
m_buffer[m_count - 1].~T();
}
}
m_count--;
}
template<class T>
bool List<T>::contains(const T& item) const
{
for (int i = 0; i < m_count; i++)
if (*(m_buffer + i) == item)
return true;
return false;
}
template<class T>
int List<T>::index_of(const T& item) const
{
for (int i = 0; i < m_count; i++)
if (*(m_buffer + i) == item)
return i;
return -1;
}
template<class T>
T List<T>::pop()
{
BLAH_ASSERT(m_count > 0, "There are no elements to pop");
m_count--;
T item = m_buffer[m_count];
m_buffer[m_count].~T();
return item;
}
template<class T>
void List<T>::dispose()
{
clear();
::operator delete (m_buffer, sizeof(T) * m_capacity);
m_buffer = nullptr;
m_count = 0;
m_capacity = 0;
}
}

View File

@ -1,8 +1,317 @@
#pragma once
#include <vector>
#include <blah/log.h>
#include <type_traits>
#include <new>
#include <string.h>
namespace Blah
{
template<typename T>
using Vector = std::vector<T>;
}
template<class T>
class Vector
{
private:
T* m_buffer;
size_t m_size;
size_t m_capacity;
public:
Vector();
Vector(int capacity);
Vector(const Vector& src);
Vector(Vector&& src) noexcept;
~Vector();
Vector& operator=(const Vector& src);
Vector& operator=(Vector&& src) noexcept;
// reserves the given amount of capacity
void reserve(size_t new_capacity);
// adds an element to the Vector
void push_back(const T& item);
// moves an element into the Vector
void push_back(T&& item);
template<class ...Args>
void emplace_back(Args&&...args);
// resizes the vector
void resize(size_t capacity);
// expands the Vector by the given amount, and returns a pointer to the first element
T* expand(size_t amount = 1);
// returns a reference to the element at the given index
T& operator[](int index);
// returns a reference to the element at the given index
const T& operator[](int index) const;
// returns a pointer to the first element
T* data() { return m_buffer; }
// returns a pointer to the first element
const T* data() const { return m_buffer; }
// returns a pointer to the first element
T* begin() { return m_buffer; }
// returns a pointer to the first element
const T* begin() const { return m_buffer; }
// returns a pointer to the last element plus 1
T* end() { return m_buffer + m_size; }
// returns a pointer to the last element plus 1
const T* end() const { return m_buffer + m_size; }
// returns the front element
T& front() { BLAH_ASSERT(m_size > 0, "Index out of range"); return *begin(); }
// returns the front element
const T& front() const { BLAH_ASSERT(m_size > 0, "Index out of range"); return *begin(); }
// returns the last element
T& back() { BLAH_ASSERT(m_size > 0, "Index out of range"); return *(end() - 1); }
// returns the last element
const T& back() const { BLAH_ASSERT(m_size > 0, "Index out of range"); return *(end() - 1); }
// clears all elements
void clear();
// removes the element at the index
void erase(const T* position);
// returns the total number of elements
size_t size() const { return m_size; }
// returns the internal buffer capacity of the Vector
size_t capacity() const { return m_capacity; }
// removes all elements and disposes the internal buffer
void dispose();
};
template<class T>
Vector<T>::Vector()
{
m_buffer = nullptr;
m_size = m_capacity = 0;
}
template<class T>
Vector<T>::Vector(int capacity)
{
m_buffer = nullptr;
m_size = m_capacity = capacity;
reserve(m_capacity);
}
template<class T>
Vector<T>::Vector(const Vector<T>& src)
{
m_buffer = (T*)(::operator new (sizeof(T) * src.m_capacity));
m_size = src.m_size;
m_capacity = src.m_capacity;
for (int n = 0; n < m_size; n++)
new (m_buffer + n) T(*(src.m_buffer + n));
}
template<class T>
Vector<T>::Vector(Vector<T>&& src) noexcept
{
m_buffer = src.m_buffer;
m_size = src.m_size;
m_capacity = src.m_capacity;
src.m_buffer = nullptr;
src.m_size = src.m_capacity = 0;
}
template<class T>
Vector<T>& Vector<T>::operator=(const Vector<T>& src)
{
clear();
if (m_capacity < src.m_size)
reserve(src.m_size);
m_size = src.m_size;
for (int n = 0; n < m_size; n++)
new (m_buffer + n) T(*(src.m_buffer + n));
return *this;
}
template<class T>
Vector<T>& Vector<T>::operator=(Vector<T>&& src) noexcept
{
dispose();
m_buffer = src.m_buffer;
m_size = src.m_size;
m_capacity = src.m_capacity;
src.m_buffer = nullptr;
src.m_size = src.m_capacity = 0;
return *this;
}
template<class T>
Vector<T>::~Vector()
{
dispose();
}
template<class T>
void Vector<T>::reserve(size_t new_capacity)
{
if (new_capacity >= m_capacity)
{
auto last_capacity = m_capacity;
if (m_capacity <= 0)
m_capacity = 8;
while (new_capacity >= m_capacity)
m_capacity = m_capacity * 2;
T* new_buffer = (T*)::operator new (sizeof(T) * m_capacity);
if (std::is_trivially_copyable<T>::value)
{
memcpy(new_buffer, m_buffer, sizeof(T) * m_size);
}
else
{
for (int n = 0; n < m_size; n++)
{
new (new_buffer + n) T(std::move(m_buffer[n]));
m_buffer[n].~T();
}
}
::operator delete (m_buffer, sizeof(T) * last_capacity);
m_buffer = new_buffer;
}
}
template<class T>
void Vector<T>::resize(size_t new_size)
{
if (new_size > m_size)
{
reserve(new_size);
for (int n = m_size; n < new_size; n++)
new (m_buffer + n) T();
}
else if (new_size < m_size)
{
for (int i = new_size; i < m_size; i ++)
m_buffer[i].~T();
}
m_size = new_size;
}
template<class T>
T* Vector<T>::expand(size_t amount)
{
reserve(m_size + amount);
for (int n = m_size; n < m_size + amount; n++)
new (m_buffer + n) T();
m_size += amount;
return (m_buffer + m_size - amount);
}
template<class T>
void Vector<T>::push_back(const T& item)
{
reserve(m_size + 1);
new (m_buffer + m_size) T(item);
m_size++;
}
template<class T>
void Vector<T>::push_back(T&& item)
{
reserve(m_size + 1);
new (m_buffer + m_size) T(std::move(item));
m_size++;
}
template<class T>
template<class ...Args>
void Vector<T>::emplace_back(Args&&...args)
{
reserve(m_size + 1);
new (m_buffer + m_size) T(std::forward<Args>(args)...);
m_size++;
}
template<class T>
T& Vector<T>::operator[](int index)
{
BLAH_ASSERT(index >= 0 && index < m_size, "Index is out of range");
return m_buffer[index];
}
template<class T>
const T& Vector<T>::operator[](int index) const
{
BLAH_ASSERT(index >= 0 && index < m_size, "Index is out of range");
return m_buffer[index];
}
template<class T>
void Vector<T>::clear()
{
for (T* it = m_buffer; it < m_buffer + m_size; it++)
it->~T();
m_size = 0;
}
template<class T>
void Vector<T>::erase(const T* position)
{
BLAH_ASSERT(position >= begin() && position < end(), "Index is out of range");
const size_t index = position - begin();
if (index < m_size - 1)
{
size_t diff = (m_size - index - 1);
if (diff <= 0) diff = 0;
if (std::is_trivially_copyable<T>::value)
{
m_buffer[index].~T();
memmove(m_buffer + index, m_buffer + index + 1, (size_t)diff * sizeof(T));
}
else
{
for (int i = index; i < m_size - 1; i++)
m_buffer[i] = std::move(m_buffer[i + 1]);
m_buffer[m_size - 1].~T();
}
}
else
{
m_buffer[index].~T();
}
m_size--;
}
template<class T>
void Vector<T>::dispose()
{
clear();
::operator delete (m_buffer, sizeof(T) * m_capacity);
m_buffer = nullptr;
m_size = 0;
m_capacity = 0;
}
}

View File

@ -67,38 +67,47 @@ namespace
}
}
#define MAKE_VERTEX(mat, px, py, tx, ty, c, m, w, f) \
{ \
Vec2( \
((px)*mat.m11) + ((py)*mat.m21) + mat.m31, \
((px)*mat.m12) + ((py)*mat.m22) + mat.m32), \
Vec2(tx, (m_batch.flip_vertically ? 1.0f - ty : ty)), \
c, m, w, f \
}
#define MAKE_VERTEX(vert, mat, px, py, tx, ty, c, m, w, f) \
(vert)->pos.x = ((px) * mat.m11) + ((py) * mat.m21) + mat.m31; \
(vert)->pos.y = ((px) * mat.m12) + ((py) * mat.m22) + mat.m32; \
(vert)->tex.x = tx; \
if (m_batch.flip_vertically) \
(vert)->tex.y = 1.0f - ty; \
else \
(vert)->tex.y = ty; \
(vert)->col = c; \
(vert)->mult = m; \
(vert)->wash = w; \
(vert)->fill = f;
#define PUSH_QUAD(px0, py0, px1, py1, px2, py2, px3, py3, tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3, col0, col1, col2, col3, mult, fill, wash) \
{ \
const int __v = (int)m_vertices.size(); \
m_batch.elements += 2; \
m_indices.insert(m_indices.end(), { __v + 0, __v + 1, __v + 2, __v + 0, __v + 2, __v + 3 }); \
m_vertices.insert(m_vertices.end(), { \
MAKE_VERTEX(m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash), \
MAKE_VERTEX(m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash), \
MAKE_VERTEX(m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash), \
MAKE_VERTEX(m_matrix, px3, py3, tx3, ty3, col3, mult, fill, wash) \
}); \
int* _i = m_indices.expand(6); \
*_i++ = m_vertices.size() + 0; \
*_i++ = m_vertices.size() + 1; \
*_i++ = m_vertices.size() + 2; \
*_i++ = m_vertices.size() + 0; \
*_i++ = m_vertices.size() + 2; \
*_i++ = m_vertices.size() + 3; \
Vertex* _v = m_vertices.expand(4); \
MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash); _v++; \
MAKE_VERTEX(_v, m_matrix, px3, py3, tx3, ty3, col3, mult, fill, wash); \
}
#define PUSH_TRIANGLE(px0, py0, px1, py1, px2, py2, tx0, ty0, tx1, ty1, tx2, ty2, col0, col1, col2, mult, fill, wash) \
{ \
const int __v = (int)m_vertices.size(); \
m_batch.elements += 1; \
m_indices.insert(m_indices.end(), { __v + 0, __v + 1, __v + 2 }); \
m_vertices.insert(m_vertices.end(), { \
MAKE_VERTEX(m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash), \
MAKE_VERTEX(m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash), \
MAKE_VERTEX(m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash) \
}); \
int* _i = m_indices.expand(3); \
*_i++ = m_vertices.size() + 0; \
*_i++ = m_vertices.size() + 1; \
*_i++ = m_vertices.size() + 2; \
Vertex* _v = m_vertices.expand(3); \
MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash); \
}
// Compares a Batcher variable, and starts a new batch if it has changed

View File

@ -0,0 +1,39 @@
#pragma once
namespace Blah
{
enum class Endian
{
Little,
Big
};
template<class T>
inline void swap_endian(T* value)
{
for (int i = 0; i < sizeof(T) / 2; i++)
{
char* _ptr = (char*)&value;
char _temp = *(_ptr + i);
*(_ptr + i) = *(_ptr + sizeof(T) - i - 1);
*(_ptr + sizeof(T) - i - 1) = _temp;
}
}
inline bool is_big_endian()
{
return (*((short*)"AB") == 0x4243);
}
inline bool is_little_endian()
{
return (*((short*)"AB") != 0x4243);
}
inline bool is_endian(const Endian& endian)
{
return
(endian == Endian::Little && is_little_endian()) ||
(endian == Endian::Big && is_big_endian());
}
}

View File

@ -5,11 +5,6 @@
using namespace Blah;
Stream::Stream()
{
}
int64_t Stream::pipe(Stream& stream, int64_t length)
{
const int BUFFER_LENGTH = 4096;
@ -32,91 +27,4 @@ int64_t Stream::pipe(Stream& stream, int64_t length)
}
return result;
}
String Stream::read_line()
{
String string;
read_line(string);
return string;
}
int64_t Stream::read_line(String& writeTo)
{
const int bufferSize = 512;
char buffer[bufferSize];
int64_t pos = position();
int64_t length = 0;
int64_t count = 0;
bool hit = false;
// read chunk-by-chunk
do
{
count = (int)read(buffer, bufferSize);
pos += count;
// check for a newline
int64_t end = count;
for (int n = 0; n < count; n++)
if (buffer[n] == '\n' || buffer[n] == '\r')
{
hit = true;
end = n;
// skip to the end of the line for future reading
int64_t lineEnd = pos - count + end + 1;
// there might be a trailing '\n'
if (buffer[n] == '\r')
{
if (end < count && buffer[n + 1] == '\n')
{
lineEnd++;
}
// our buffer aligned perfectly ..... :/
else if (count == bufferSize && end == count)
{
char ch;
if (read(&ch, 1) != 0 && ch == '\n')
lineEnd++;
}
}
seek(lineEnd);
break;
}
// copy to string
writeTo.set_length((int)(length + end));
memcpy(writeTo.cstr() + length, buffer, (size_t)end);
*(writeTo.cstr() + length + end) = '\0';
// increment length
length += end;
} while (!hit && count >= bufferSize);
return length;
}
String Stream::read_string(int length)
{
if (length >= 0)
{
String str;
str.set_length(length);
read_into(str.cstr(), length);
str[length] = '\0';
return str;
}
else
{
String str;
char next;
while (read_into(&next, 1) && next != '\0')
str.append(next);
return str;
}
}

View File

@ -1,29 +1,14 @@
#pragma once
#include <inttypes.h>
#include <blah/containers/str.h>
#define BLAH_SWAP_ENDIAN(value, type) \
for (int i = 0; i < sizeof(type) / 2; i ++) { \
uint8_t* _ptr = (uint8_t*)&value;\
uint8_t _temp = *(_ptr + i); \
*(_ptr + i) = *(_ptr + sizeof(type) - i - 1); \
*(_ptr + sizeof(type) - i - 1) = _temp; \
}
#define BLAH_BIG_ENDIAN (*((short*)"AB") == 0x4243)
#include <blah/streams/endian.h>
namespace Blah
{
enum class Endian
{
Little,
Big
};
class Stream
{
public:
Stream();
Stream() = default;
Stream(const Stream&) = delete;
Stream& operator=(const Stream&) = delete;
@ -53,44 +38,92 @@ namespace Blah
// pipes the contents of this tream to another stream
int64_t pipe(Stream& to, int64_t length);
// reads a single line from this stream (up until \r or \n)
String read_line();
// reada a single line from this stream, to the given string (up until \r or \n)
int64_t read_line(String& writeTo);
// reads a string of a given length, or until a null terminator if -1
String read_string(int length = -1);
// reads the amount of bytes into the given buffer, and returns the amount read
int64_t read(void* buffer, int64_t length) { return read_into(buffer, length); }
template<class T>
T read() { return read<T>(Endian::Little); }
// reads a string. if length < 0, assumes null-terminated
String read_string(int length = -1)
{
String result;
if (length < 0)
{
char next;
while (read(&next, 1) && next != '\0')
result.append(next);
}
else
{
result.set_length(length);
read_into(result.cstr(), length);
}
return result;
}
String read_line()
{
String result;
char next;
while (read(&next, 1) && next != '\n' && next != '\0')
result.append(next);
return result;
}
// reads a number
template<class T>
T read()
{
return read<T>(Endian::Little);
}
// reads a number
template<class T>
T read(Endian endian)
{
T value;
read(&value, sizeof(T));
if ((endian == Endian::Little && BLAH_BIG_ENDIAN) || (endian == Endian::Big && !BLAH_BIG_ENDIAN))
BLAH_SWAP_ENDIAN(value, T);
return value;
T result;
read(&result, sizeof(T));
if (!Blah::is_endian(endian))
Blah::swap_endian(&result);
return result;
}
int64_t write(const void* buffer, int64_t length) { return write_from(buffer, length); }
// writes the amount of bytes to the stream from the given buffer, and returns the amount written
int64_t write(const void* buffer, int64_t length)
{
return write_from(buffer, length);
}
// writes a null-terminated string, and returns the amount written
int64_t write_cstr(const Str& string)
{
return write(string.cstr(), string.length() + 1);
}
// writes a null-terminated string, and returns the amount written
int64_t write_cstr(const char* cstr)
{
return write(cstr, strlen(cstr) + 1);
}
// writes a number
template<class T>
int64_t write(const T& value) { return write<T>(value, Endian::Little); }
int64_t write(const T& value)
{
return write<T>(value, Endian::Little);
}
// writes a number
template<class T>
int64_t write(const T& value, Endian endian)
{
T writing = value;
if ((endian == Endian::Little && BLAH_BIG_ENDIAN) || (endian == Endian::Big && !BLAH_BIG_ENDIAN))
BLAH_SWAP_ENDIAN(writing, T);
if (!Blah::is_endian(endian))
Blah::swap_endian(&writing);
return write(&writing, sizeof(T));
}
@ -100,7 +133,6 @@ namespace Blah
// writes from the stream from the given buffer, and returns the number of bytes written
virtual int64_t write_from(const void* buffer, int64_t length) = 0;
};
}