/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef COMMON_DATA_IO_H
#define COMMON_DATA_IO_H
#include "common/scummsys.h"
namespace Common {
enum class EndianStorageFormat {
Big,
Little,
};
// Traits for a storage format. You can specialize this to make more storage formats
// that have their own behavior.
template
struct DataFormatTraits {
};
template<>
struct DataFormatTraits {
static inline bool isLittleEndian(EndianStorageFormat storageFormat) {
return storageFormat == EndianStorageFormat::Little;
}
};
template
struct SimpleDataIO {
static const uint kMaxSize = sizeof(T);
static uint computeSize(TDataFormat dataFormat);
static void encode(TDataFormat dataFormat, byte *data, const T &value);
static void decode(TDataFormat dataFormat, const byte *data, T &value);
};
template
uint SimpleDataIO::computeSize(TDataFormat dataFormat) {
return sizeof(T);
}
template
void SimpleDataIO::encode(TDataFormat dataFormat, byte *data, const T &value) {
const byte *valueBytes = reinterpret_cast(&value);
byte *dataBytes = reinterpret_cast(data);
const bool isTargetLE = DataFormatTraits::isLittleEndian(dataFormat);
#ifdef SCUMM_LITTLE_ENDIAN
const bool isSystemLE = true;
#endif
#ifdef SCUMM_BIG_ENDIAN
const bool isSystemLE = false;
#endif
const bool requiresSwap = (isSystemLE != isTargetLE);
byte temp[sizeof(T)];
if (requiresSwap) {
for (uint i = 0; i < sizeof(T); i++)
temp[i] = valueBytes[sizeof(T) - 1 - i];
} else {
for (uint i = 0; i < sizeof(T); i++)
temp[i] = valueBytes[i];
}
for (uint i = 0; i < sizeof(T); i++)
dataBytes[i] = temp[i];
}
template
void SimpleDataIO::decode(TDataFormat dataFormat, const byte *data, T &value) {
byte *valueBytes = reinterpret_cast(&value);
const byte *dataBytes = reinterpret_cast(data);
const bool isTargetLE = DataFormatTraits::isLittleEndian(dataFormat);
#ifdef SCUMM_LITTLE_ENDIAN
const bool isSystemLE = true;
#endif
#ifdef SCUMM_BIG_ENDIAN
const bool isSystemLE = false;
#endif
const bool requiresSwap = (isSystemLE != isTargetLE);
byte temp[sizeof(T)];
if (requiresSwap) {
for (uint i = 0; i < sizeof(T); i++)
temp[i] = dataBytes[sizeof(T) - 1 - i];
} else {
for (uint i = 0; i < sizeof(T); i++)
temp[i] = dataBytes[i];
}
for (uint i = 0; i < sizeof(T); i++)
valueBytes[i] = temp[i];
}
template
struct DataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataIO : public SimpleDataIO {
};
template
struct DataMultipleIO;
template
struct DataMultipleIO {
static const uint kMaxSize = DataIO::kMaxSize;
static uint computeSize(TDataFormat dataFormat);
static void encode(TDataFormat dataFormat, byte *data, const T &value);
static void decode(TDataFormat dataFormat, const byte *data, T &value);
};
template
uint DataMultipleIO::computeSize(TDataFormat dataFormat) {
return DataIO::computeSize(dataFormat);
}
template
void DataMultipleIO::encode(TDataFormat dataFormat, byte *data, const T &value) {
return DataIO::encode(dataFormat, data, value);
}
template
void DataMultipleIO::decode(TDataFormat dataFormat, const byte *data, T &value) {
return DataIO::decode(dataFormat, data, value);
}
template
struct DataMultipleIO {
static const uint kMaxSize = DataIO::kMaxSize * TSize;
static uint computeSize(TDataFormat dataFormat);
static void encode(TDataFormat dataFormat, byte *data, const T (&value)[TSize]);
static void decode(TDataFormat dataFormat, const byte *data, T (&value)[TSize]);
};
template
uint DataMultipleIO::computeSize(TDataFormat dataFormat) {
return DataMultipleIO::computeSize(dataFormat) * TSize;
}
template
void DataMultipleIO::encode(TDataFormat dataFormat, byte *data, const T (&value)[TSize]) {
const uint elementSize = DataIO::computeSize(dataFormat);
for (uint i = 0; i < TSize; i++)
DataMultipleIO::encode(dataFormat, data + elementSize * i, value[i]);
}
template
void DataMultipleIO::decode(TDataFormat dataFormat, const byte *data, T (&value)[TSize]) {
const uint elementSize = DataIO::computeSize(dataFormat);
for (uint i = 0; i < TSize; i++)
DataMultipleIO::decode(dataFormat, data + elementSize * i, value[i]);
}
template
struct DataMultipleIO {
static const uint kMaxSize = DataIO::kMaxSize + DataMultipleIO::kMaxSize;
static uint computeSize(TDataFormat dataFormat);
static void encode(TDataFormat dataFormat, byte *data, const T &firstValue, const TMore &...moreValues);
static void decode(TDataFormat dataFormat, const byte *data, T &firstValue, TMore &...moreValues);
};
template
uint DataMultipleIO::computeSize(TDataFormat dataFormat) {
return DataMultipleIO::computeSize(dataFormat) + DataMultipleIO::computeSize(dataFormat);
}
template
void DataMultipleIO::encode(TDataFormat dataFormat, byte *data, const T &firstValue, const TMore &...moreValues) {
DataMultipleIO::encode(dataFormat, data, firstValue);
DataMultipleIO::encode(dataFormat, data + DataMultipleIO::computeSize(dataFormat), moreValues...);
}
template
void DataMultipleIO::decode(TDataFormat dataFormat, const byte *data, T &firstValue, TMore &...moreValues) {
DataMultipleIO::decode(dataFormat, data, firstValue);
DataMultipleIO::decode(dataFormat, data + DataMultipleIO::computeSize(dataFormat), moreValues...);
}
} // End of namespace Common
#endif