diff --git a/include/blah/numerics/calc.h b/include/blah/numerics/calc.h index afe519a..061c705 100644 --- a/include/blah/numerics/calc.h +++ b/include/blah/numerics/calc.h @@ -3,6 +3,12 @@ namespace Blah { + enum class Endian + { + Little, + Big + }; + namespace Calc { constexpr float PI = 3.141592653f; @@ -69,8 +75,33 @@ namespace Blah float lerp(float a, float b, float t); - bool is_big_endian(); + template + 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; + } + } - bool is_little_endian(); + 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()); + } }; } diff --git a/include/blah/streams/endian.h b/include/blah/streams/endian.h deleted file mode 100644 index 02275fb..0000000 --- a/include/blah/streams/endian.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -namespace Blah -{ - enum class Endian - { - Little, - Big - }; - - template - 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()); - } -} \ No newline at end of file diff --git a/include/blah/streams/stream.h b/include/blah/streams/stream.h index 737a1d0..51c09ca 100644 --- a/include/blah/streams/stream.h +++ b/include/blah/streams/stream.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include namespace Blah @@ -49,22 +49,16 @@ namespace Blah String read_line(); // reads a number - template::value, T>::type> - T read() - { - return read(Endian::Little); - } - - // reads a number - template::value, T>::type> - T read(Endian endian) - { - T result; - read(&result, sizeof(T)); - if (!Blah::is_endian(endian)) - Blah::swap_endian(&result); - return result; - } + u8 read_u8 (Endian endian = Endian::Little); + u16 read_u16(Endian endian = Endian::Little); + u32 read_u32(Endian endian = Endian::Little); + u64 read_u64(Endian endian = Endian::Little); + i8 read_i8 (Endian endian = Endian::Little); + i16 read_i16(Endian endian = Endian::Little); + i32 read_i32(Endian endian = Endian::Little); + i64 read_i64(Endian endian = Endian::Little); + f32 read_f32(Endian endian = Endian::Little); + f64 read_f64(Endian endian = Endian::Little); // writes the amount of bytes to the stream from the given buffer, and returns the amount written size_t write(const void* buffer, size_t length); @@ -72,24 +66,17 @@ namespace Blah // writes the contents of a string to the stream size_t write(const String& string); - // writes a number - template::value, T>::type> - size_t write(const T& value) - { - return write(value, Endian::Little); - } - - // writes a number - template::value, T>::type> - size_t write(const T& value, Endian endian) - { - T writing = value; - - if (!Blah::is_endian(endian)) - Blah::swap_endian(&writing); - - return write(&writing, sizeof(T)); - } + // writes a number, returns number of bytes written + size_t write_u8 (u8 value, Endian endian = Endian::Little); + size_t write_u16(u16 value, Endian endian = Endian::Little); + size_t write_u32(u32 value, Endian endian = Endian::Little); + size_t write_u64(u64 value, Endian endian = Endian::Little); + size_t write_i8 (i8 value, Endian endian = Endian::Little); + size_t write_i16(i16 value, Endian endian = Endian::Little); + size_t write_i32(i32 value, Endian endian = Endian::Little); + size_t write_i64(i64 value, Endian endian = Endian::Little); + size_t write_f32(f32 value, Endian endian = Endian::Little); + size_t write_f64(f64 value, Endian endian = Endian::Little); protected: // reads the amount of bytes into the given buffer, and returns the amount read diff --git a/src/images/aseprite.cpp b/src/images/aseprite.cpp index 72d90f0..1c09ac2 100644 --- a/src/images/aseprite.cpp +++ b/src/images/aseprite.cpp @@ -90,10 +90,10 @@ void Aseprite::parse(Stream& stream) // header { // filesize - stream.read(Endian::Little); + stream.read_u32(Endian::Little); // magic number - auto magic = stream.read(Endian::Little); + auto magic = stream.read_u16(Endian::Little); if (magic != 0xA5E0) { BLAH_ASSERT(false, "File is not a valid Aseprite file"); @@ -101,21 +101,21 @@ void Aseprite::parse(Stream& stream) } // main info - frame_count = stream.read(Endian::Little); - width = stream.read(Endian::Little); - height = stream.read(Endian::Little); - mode = static_cast(stream.read(Endian::Little) / 8); + frame_count = stream.read_u16(Endian::Little); + width = stream.read_u16(Endian::Little); + height = stream.read_u16(Endian::Little); + mode = static_cast(stream.read_u16(Endian::Little) / 8); // don't care about other info - stream.read(Endian::Little); // Flags - stream.read(Endian::Little); // Speed (deprecated) - stream.read(Endian::Little); // Should be 0 - stream.read(Endian::Little); // Should be 0 - stream.read(Endian::Little); // Palette entry + stream.read_u32(Endian::Little); // Flags + stream.read_u16(Endian::Little); // Speed (deprecated) + stream.read_u32(Endian::Little); // Should be 0 + stream.read_u32(Endian::Little); // Should be 0 + stream.read_u8(Endian::Little); // Palette entry stream.seek(stream.position() + 3); // Ignore these bytes - stream.read(Endian::Little); // Number of colors (0 means 256 for old sprites) - stream.read(Endian::Little); // Pixel width - stream.read(Endian::Little); // Pixel height + stream.read_u16(Endian::Little); // Number of colors (0 means 256 for old sprites) + stream.read_i8(Endian::Little); // Pixel width + stream.read_i8(Endian::Little); // Pixel height stream.seek(stream.position() + 92); // For Future } @@ -125,22 +125,22 @@ void Aseprite::parse(Stream& stream) for (int i = 0; i < frame_count; i++) { auto frameStart = stream.position(); - auto frameEnd = frameStart + stream.read(Endian::Little); + auto frameEnd = frameStart + stream.read_u32(Endian::Little); unsigned int chunks = 0; // frame header { - auto magic = stream.read(Endian::Little); // magic number + auto magic = stream.read_u16(Endian::Little); // magic number if (magic != 0xF1FA) { BLAH_ASSERT(false, "File is not a valid Aseprite file"); return; } - auto old_chunk_count = stream.read(Endian::Little); - frames[i].duration = stream.read(Endian::Little); + auto old_chunk_count = stream.read_u16(Endian::Little); + frames[i].duration = stream.read_u16(Endian::Little); stream.seek(stream.position() + 2); // for future - auto new_chunk_count = stream.read(Endian::Little); + auto new_chunk_count = stream.read_u32(Endian::Little); if (old_chunk_count == 0xFFFF) chunks = new_chunk_count; @@ -155,8 +155,8 @@ void Aseprite::parse(Stream& stream) for (unsigned int j = 0; j < chunks; j++) { auto chunkStart = stream.position(); - auto chunkEnd = chunkStart + stream.read(Endian::Little); - auto chunkType = static_cast(stream.read(Endian::Little)); + auto chunkEnd = chunkStart + stream.read_u32(Endian::Little); + auto chunkType = static_cast(stream.read_u16(Endian::Little)); switch (chunkType) { @@ -181,17 +181,17 @@ void Aseprite::parse_layer(Stream& stream, int frame) layers.emplace_back(); auto& layer = layers.back(); - layer.flag = static_cast(stream.read(Endian::Little)); + layer.flag = static_cast(stream.read_u16(Endian::Little)); layer.visible = ((int)layer.flag & (int)LayerFlags::Visible) == (int)LayerFlags::Visible; - layer.type = static_cast(stream.read(Endian::Little)); - layer.child_level = stream.read(Endian::Little); - stream.read(Endian::Little); // width - stream.read(Endian::Little); // height - layer.blendmode = stream.read(Endian::Little); - layer.alpha = stream.read(Endian::Little); + layer.type = static_cast(stream.read_u16(Endian::Little)); + layer.child_level = stream.read_u16(Endian::Little); + stream.read_u16(Endian::Little); // width + stream.read_u16(Endian::Little); // height + layer.blendmode = stream.read_u16(Endian::Little); + layer.alpha = stream.read_u8(Endian::Little); stream.seek(stream.position() + 3); // for future - layer.name.set_length(stream.read(Endian::Little)); + layer.name.set_length(stream.read_u16(Endian::Little)); stream.read(layer.name.cstr(), layer.name.length()); layer.userdata.color = 0xffffff; @@ -205,20 +205,20 @@ void Aseprite::parse_cel(Stream& stream, int frameIndex, size_t maxPosition) frame.cels.emplace_back(); auto& cel = frame.cels.back(); - cel.layer_index = stream.read(Endian::Little); - cel.x = stream.read(Endian::Little); - cel.y = stream.read(Endian::Little); - cel.alpha = stream.read(Endian::Little); + cel.layer_index = stream.read_u16(Endian::Little); + cel.x = stream.read_u16(Endian::Little); + cel.y = stream.read_u16(Endian::Little); + cel.alpha = stream.read_u8(Endian::Little); cel.linked_frame_index = -1; - auto celType = stream.read(Endian::Little); + auto celType = stream.read_u16(Endian::Little); stream.seek(stream.position() + 7); // RAW or DEFLATE if (celType == 0 || celType == 2) { - auto width = stream.read(Endian::Little); - auto height = stream.read(Endian::Little); + auto width = stream.read_u16(Endian::Little); + auto height = stream.read_u16(Endian::Little); auto count = width * height * (int)mode; cel.image = Image(width, height); @@ -274,7 +274,7 @@ void Aseprite::parse_cel(Stream& stream, int frameIndex, size_t maxPosition) // this cel directly references a previous cel else if (celType == 1) { - cel.linked_frame_index = stream.read(Endian::Little); + cel.linked_frame_index = stream.read_u16(Endian::Little); } // draw to frame if visible @@ -290,21 +290,21 @@ void Aseprite::parse_cel(Stream& stream, int frameIndex, size_t maxPosition) void Aseprite::parse_palette(Stream& stream, int frame) { - /* size */ stream.read(Endian::Little); - auto start = stream.read(Endian::Little); - auto end = stream.read(Endian::Little); + /* size */ stream.read_u32(Endian::Little); + auto start = stream.read_u32(Endian::Little); + auto end = stream.read_u32(Endian::Little); stream.seek(stream.position() + 8); palette.resize(palette.size() + (end - start + 1)); for (int p = 0, len = static_cast(end - start) + 1; p < len; p++) { - auto hasName = stream.read(Endian::Little); - palette[start + p] = stream.read(Endian::Little); + auto hasName = stream.read_u16(Endian::Little); + palette[start + p] = stream.read_u32(Endian::Little); if (hasName & 0xF000) { - int len = stream.read(Endian::Little); + int len = stream.read_u16(Endian::Little); stream.seek(stream.position() + len); } } @@ -314,38 +314,38 @@ void Aseprite::parse_user_data(Stream& stream, int frame) { if (m_last_userdata != nullptr) { - auto flags = stream.read(Endian::Little); + auto flags = stream.read_u32(Endian::Little); // has text if (flags & (1 << 0)) { - m_last_userdata->text.set_length(stream.read(Endian::Little)); + m_last_userdata->text.set_length(stream.read_u16(Endian::Little)); stream.read(m_last_userdata->text.cstr(), m_last_userdata->text.length()); } // has color if (flags & (1 << 1)) - m_last_userdata->color = stream.read(Endian::Little); + m_last_userdata->color = stream.read_u32(Endian::Little); } } void Aseprite::parse_tag(Stream& stream, int frame) { - auto count = stream.read(Endian::Little); + auto count = stream.read_u16(Endian::Little); stream.seek(stream.position() + 8); for (int t = 0; t < count; t++) { Tag tag; - tag.from = stream.read(Endian::Little); - tag.to = stream.read(Endian::Little); - tag.loops = static_cast(stream.read(Endian::Little)); + tag.from = stream.read_u16(Endian::Little); + tag.to = stream.read_u16(Endian::Little); + tag.loops = static_cast(stream.read_i8(Endian::Little)); stream.seek(stream.position() + 8); - tag.color = Color(stream.read(), stream.read(), stream.read(Endian::Little), 255); + tag.color = Color(stream.read_i8(), stream.read_i8(), stream.read_i8(Endian::Little), 255); stream.seek(stream.position() + 1); - tag.name.set_length(stream.read(Endian::Little)); + tag.name.set_length(stream.read_u16(Endian::Little)); stream.read(tag.name.cstr(), tag.name.length()); tags.push_back(tag); @@ -354,12 +354,12 @@ void Aseprite::parse_tag(Stream& stream, int frame) void Aseprite::parse_slice(Stream& stream, int frame) { - int count = stream.read(Endian::Little); - int flags = stream.read(Endian::Little); - stream.read(Endian::Little); // reserved + int count = stream.read_u32(Endian::Little); + int flags = stream.read_u32(Endian::Little); + stream.read_u32(Endian::Little); // reserved String name; - name.set_length(stream.read(Endian::Little)); + name.set_length(stream.read_u16(Endian::Little)); stream.read(name.cstr(), name.length()); for (int s = 0; s < count; s++) @@ -368,19 +368,19 @@ void Aseprite::parse_slice(Stream& stream, int frame) auto& slice = slices.back(); slice.name = name; - slice.frame = stream.read(Endian::Little); - slice.origin.x = stream.read(Endian::Little); - slice.origin.y = stream.read(Endian::Little); - slice.width = stream.read(Endian::Little); - slice.height = stream.read(Endian::Little); + slice.frame = stream.read_u32(Endian::Little); + slice.origin.x = stream.read_i32(Endian::Little); + slice.origin.y = stream.read_i32(Endian::Little); + slice.width = stream.read_u32(Endian::Little); + slice.height = stream.read_u32(Endian::Little); // 9 slice (ignored atm) if (flags & (1 << 0)) { - stream.read(Endian::Little); - stream.read(Endian::Little); - stream.read(Endian::Little); - stream.read(Endian::Little); + stream.read_i32(Endian::Little); + stream.read_i32(Endian::Little); + stream.read_u32(Endian::Little); + stream.read_u32(Endian::Little); } // pivot point @@ -388,8 +388,8 @@ void Aseprite::parse_slice(Stream& stream, int frame) if (flags & (1 << 1)) { slice.has_pivot = true; - slice.pivot.x = stream.read(Endian::Little); - slice.pivot.y = stream.read(Endian::Little); + slice.pivot.x = stream.read_u32(Endian::Little); + slice.pivot.y = stream.read_u32(Endian::Little); } slice.userdata.color = 0xffffff; diff --git a/src/numerics/calc.cpp b/src/numerics/calc.cpp index a2b952f..8d1553c 100644 --- a/src/numerics/calc.cpp +++ b/src/numerics/calc.cpp @@ -112,14 +112,4 @@ float Calc::angle_lerp(float radians_a, float radians_b, float p) float Calc::lerp(float a, float b, float t) { return a + (b - a) * t; -} - -bool Calc::is_big_endian() -{ - return (*((short*)"AB") == 0x4243); -} - -bool Calc::is_little_endian() -{ - return (*((short*)"AB") != 0x4243); } \ No newline at end of file diff --git a/src/streams/stream.cpp b/src/streams/stream.cpp index 6e3cc98..49a56cf 100644 --- a/src/streams/stream.cpp +++ b/src/streams/stream.cpp @@ -73,3 +73,134 @@ size_t Stream::write(const String& string) { return write(string.begin(), string.length()); } + +u8 Stream::read_u8(Endian endian) +{ + u8 value; read_data(&value, sizeof(u8)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +u16 Stream::read_u16(Endian endian) +{ + u16 value; read_data(&value, sizeof(u16)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +u32 Stream::read_u32(Endian endian) +{ + u32 value; read_data(&value, sizeof(u32)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +u64 Stream::read_u64(Endian endian) +{ + u64 value; read_data(&value, sizeof(u64)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +i8 Stream::read_i8(Endian endian) +{ + i8 value; read_data(&value, sizeof(i8)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +i16 Stream::read_i16(Endian endian) +{ + i16 value; read_data(&value, sizeof(i16)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +i32 Stream::read_i32(Endian endian) +{ + i32 value; read_data(&value, sizeof(i32)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +i64 Stream::read_i64(Endian endian) +{ + i64 value; read_data(&value, sizeof(i64)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +float Stream::read_f32(Endian endian) +{ + float value; read_data(&value, sizeof(float)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +double Stream::read_f64(Endian endian) +{ + double value; read_data(&value, sizeof(double)); + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return value; +} + +size_t Stream::write_u8(u8 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(u8)); +} + +size_t Stream::write_u16(u16 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(u16)); +} + +size_t Stream::write_u32(u32 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(u32)); +} + +size_t Stream::write_u64(u64 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(u64)); +} + +size_t Stream::write_i8(i8 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(i8)); +} + +size_t Stream::write_i16(i16 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(i16)); +} + +size_t Stream::write_i32(i32 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(i32)); +} + +size_t Stream::write_i64(i64 value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(i64)); +} + +size_t Stream::write_f32(float value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(float)); +} + +size_t Stream::write_f64(double value, Endian endian) +{ + if (!Calc::is_endian(endian)) Calc::swap_endian(&value); + return write_data(&value, sizeof(double)); +} +