87 lines
3.3 KiB
C++
87 lines
3.3 KiB
C++
// Copyright 2022, FOSS-VG Developers and Contributers
|
|
//
|
|
// Author(s):
|
|
// BodgeMaster, Shwoomple
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU Affero General Public License as published
|
|
// by the Free Software Foundation, version 3.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// version 3 along with this program.
|
|
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
|
|
#include <cstdint>
|
|
#include <vector>
|
|
|
|
#include "error.hpp"
|
|
|
|
namespace VarInt {
|
|
|
|
// up to 5 bytes, least significant byte first, most significant bit
|
|
// indicates whether the next byte is still part of the number
|
|
ErrorOr<int32_t> fromVar32(std::vector<uint8_t> data, uint64_t initialPosition=0, uint8_t* processedBytes=nullptr) {
|
|
if (initialPosition > data.size()) {
|
|
return ErrorOr<int32_t>(true, ErrorCodes::OUT_OF_RANGE);
|
|
}
|
|
|
|
int32_t returnValue = 0;
|
|
uint64_t currentPosition = initialPosition;
|
|
uint8_t bits = 0;
|
|
while (data[currentPosition] & 0b10000000 && currentPosition < initialPosition+4) {
|
|
returnValue = returnValue + ((0b01111111 & data[currentPosition]) << bits);
|
|
|
|
(*processedBytes)++;
|
|
bits += 7;
|
|
currentPosition++;
|
|
// check after increasing so we don't need to check outside the loop
|
|
if (currentPosition > data.size()) {
|
|
return ErrorOr<int32_t>(true, ErrorCodes::OVERRUN);
|
|
}
|
|
|
|
}
|
|
if (data[currentPosition] & 0b10000000) {
|
|
return ErrorOr<int32_t>(true, ErrorCodes::OVERFLOW);
|
|
}
|
|
returnValue = returnValue + ((0b01111111 & data[currentPosition]) << bits);
|
|
(*processedBytes)++;
|
|
|
|
return ErrorOr<int32_t>(returnValue);
|
|
}
|
|
|
|
// up to 10 bytes, least significant byte first, most significant bit
|
|
// indicates whether the next byte is still part of the number
|
|
ErrorOr<int64_t> fromVar64(std::vector<uint8_t> data, uint64_t initialPosition=0, uint8_t* processedBytes=nullptr) {
|
|
if (initialPosition > data.size()) {
|
|
return ErrorOr<int64_t>(true, ErrorCodes::OUT_OF_RANGE);
|
|
}
|
|
|
|
int64_t returnValue = 0;
|
|
uint64_t currentPosition = initialPosition;
|
|
uint8_t bits = 0;
|
|
while (data[currentPosition] & 0b10000000 && currentPosition < initialPosition+9) {
|
|
returnValue = returnValue + ((0b01111111 & data[currentPosition]) << bits);
|
|
|
|
(*processedBytes)++;
|
|
bits += 7;
|
|
currentPosition++;
|
|
// check after increasing so we don't need to check outside the loop
|
|
if (currentPosition > data.size()) {
|
|
return ErrorOr<int64_t>(true, ErrorCodes::OVERRUN);
|
|
}
|
|
}
|
|
if (data[currentPosition] & 0b10000000) {
|
|
return ErrorOr<int64_t>(true, ErrorCodes::OVERFLOW);
|
|
}
|
|
returnValue = returnValue + ((0b00000001 & data[currentPosition]) << bits);
|
|
(*processedBytes)++;
|
|
|
|
return ErrorOr<int64_t>(returnValue);
|
|
}
|
|
}
|