File indexing completed on 2025-01-05 04:01:21

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "binary_stream.hpp"
0008 
0009 #include <array>
0010 #include <QtEndian>
0011 
0012 glaxnimate::io::BinaryInputStream::BinaryInputStream(QIODevice* file):
0013     BinaryInputStream(file->readAll())
0014 {
0015 }
0016 
0017 glaxnimate::io::BinaryInputStream::BinaryInputStream(QByteArray data):
0018     data(std::move(data)),
0019     data_start(this->data.data()),
0020     data_end(data_start + this->data.size())
0021 {
0022 }
0023 
0024 void glaxnimate::io::BinaryInputStream::on_overflow()
0025 {
0026     error = true;
0027 }
0028 
0029 bool glaxnimate::io::BinaryInputStream::eof() const
0030 {
0031     return data_start >= data_end;
0032 }
0033 
0034 bool glaxnimate::io::BinaryInputStream::has_error() const
0035 {
0036     return error;
0037 }
0038 
0039 QByteArray glaxnimate::io::BinaryInputStream::read(qint64 max_size)
0040 {
0041     if ( data_start + max_size < data_end )
0042     {
0043         data_start += max_size;
0044         return QByteArray(data_start - max_size, max_size);
0045     }
0046 
0047     on_overflow();
0048     return {};
0049 }
0050 
0051 quint8 glaxnimate::io::BinaryInputStream::next()
0052 {
0053     if ( data_start < data_end )
0054     {
0055         ++data_start;
0056         return data_start[-1];
0057     }
0058 
0059     on_overflow();
0060     return {};
0061 }
0062 
0063 quint32 glaxnimate::io::BinaryInputStream::read_uint32_le()
0064 {
0065     static_assert(sizeof(quint32) == 4);
0066     auto data = read(4);
0067     if ( data.size() == 4 )
0068     {
0069         return qFromLittleEndian<quint32>(data.data());
0070     }
0071     else
0072     {
0073         return 0;
0074     }
0075 }
0076 
0077 glaxnimate::io::Float32 glaxnimate::io::BinaryInputStream::read_float32_le()
0078 {
0079     static_assert(sizeof(Float32) == 4);
0080     auto data = read(4);
0081     if ( data.size() == 4 )
0082     {
0083         return qFromLittleEndian<Float32>(data.data());
0084     }
0085     else
0086     {
0087         on_overflow();
0088         return 0;
0089     }
0090 }
0091 
0092 glaxnimate::io::VarUint glaxnimate::io::BinaryInputStream::read_uint_leb128()
0093 {
0094     VarUint result = 0;
0095     VarUint shift = 0;
0096     while (true)
0097     {
0098         quint8 byte = next();
0099         if ( error )
0100             return 0;
0101 
0102         result |= VarUint(byte & 0x7f) << shift;
0103 
0104         if ( !(byte & 0x80) )
0105             return result;
0106 
0107         shift += 7;
0108     }
0109 }
0110 
0111 glaxnimate::io::BinaryOutputStream::BinaryOutputStream(QIODevice* file)
0112     : file(file)
0113 {
0114 }
0115 
0116 void glaxnimate::io::BinaryOutputStream::write(const QByteArray& data)
0117 {
0118     file->write(data);
0119 }
0120 
0121 void glaxnimate::io::BinaryOutputStream::write_byte(quint8 v)
0122 {
0123     file->putChar(v);
0124 }
0125 
0126 void glaxnimate::io::BinaryOutputStream::write_float32_le(glaxnimate::io::Float32 v)
0127 {
0128     static_assert(sizeof(Float32) == 4);
0129     std::array<quint8, 4> data;
0130     qToLittleEndian(v, data.data());
0131     file->write((const char*)data.data(), 4);
0132 }
0133 
0134 void glaxnimate::io::BinaryOutputStream::write_uint32_le(quint32 v)
0135 {
0136     static_assert(sizeof(quint32) == 4);
0137     std::array<quint8, 4> data;
0138     qToLittleEndian(v, data.data());
0139     file->write((const char*)data.data(), 4);
0140 }
0141 
0142 void glaxnimate::io::BinaryOutputStream::write_uint_leb128(glaxnimate::io::VarUint v)
0143 {
0144     while ( true )
0145     {
0146         quint8 byte = v & 0x7f;
0147         v >>= 7;
0148         if ( v == 0 )
0149         {
0150             write_byte(byte);
0151             break;
0152         }
0153         write_byte(byte | 0x80);
0154     }
0155 }