Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // AxBinaryReader.cpp - read AX binary files
- #include <io.h>
- #include <iomanip>
- #include <iostream>
- #include <fstream>
- #include <fcntl.h>
- #include <string>
- #include <cstdint>
- #include <ctime>
- #include <math.h>
- #include <combaseapi.h>
- #include <map>
- enum class Type { String, Integer, Real, Date, Enum, RString, UtcDateTime, Container, VarString,
- StringArray = 0x20, IntArray, RealArray, DateArray, EnumArray, RStringArray, UtcArray,
- Record = 0x1D, BLOB = 0x30, Int64 = 0x31, Int64Array = 0x33, Guid = 0x2D, Record2 = 0xFB, EnumName = 0xFC, Start = 0xFD, End = 0xFF };
- std::map<int, std::wstring> Field = {{ 0xF000, L"modifiedDateTime" },
- { 0xF001, L"modifiedTime" },
- { 0xF002, L"modifiedBy" },
- { 0xF003, L"modifiedTransactionId" },
- { 0xF004, L"createdDateTime" },
- { 0xF005, L"createdTime" },
- { 0xF006, L"createdBy" },
- { 0xF007, L"createdTransactionId" },
- { 0xF008, L"dataAreaId" },
- { 0xF009, L"sequenceNum" },
- { 0xF00A, L"recVersion" },
- { 0xF00B, L"unionAllBranchId" },
- { 0xF00C, L"rowNumber" },
- { 0xF00D, L"relationType" },
- { 0xF00E, L"Partition" },
- { 0xFFFE, L"RecId" },
- { 0xFFFF, L"TableId" },
- };
- void die(const std::string& msg)
- {
- std::cerr << msg << std::endl;
- exit(1);
- }
- template <typename T1, typename T2>
- void testEq(T1 test, T2 value)
- {
- if (test != value)
- {
- die("Expected " + std::to_string(value) + ", got " + std::to_string(test));
- }
- }
- template <typename T>
- T read(std::ifstream &fs)
- {
- T x{};
- fs.read((char *)(&x), sizeof(T));
- return x;
- }
- auto readGuid(std::ifstream &fs)
- {
- GUID x;
- fs.read((char *)(&x), 16);
- wchar_t guid[40];
- StringFromGUID2(x, guid, sizeof(guid));
- guid[0] = guid[37] = '"';
- std::wcout << guid;
- return 16;
- }
- auto readEnum(std::ifstream &fs, bool withType)
- {
- auto val = read<uint8_t>(fs);
- auto type = withType ? read<uint16_t>(fs) : 0;
- if ((type == 0xF000) & ((val == 0) | (val == 1)))
- std::wcout << (val ? L"true" : L"false");
- else
- std::wcout << +val;
- return withType ? 3 : 1;
- }
- auto ignoreString(std::ifstream &fs)
- {
- size_t size = 2;
- for (auto ch = read<wchar_t>(fs); ch; ch = read<wchar_t>(fs))
- {
- size += 2;
- }
- return size;
- }
- std::pair<int, int> readString(std::ifstream &fs)
- {
- int size = 2;
- int number = 0;
- for (auto ch = read<wchar_t>(fs); ch; ch = read<wchar_t>(fs))
- {
- size += 2;
- switch (ch)
- {
- case L'"':
- std::wcout << '\\' << '"';
- break;
- case L'\\':
- std::wcout << '\\' << '\\';
- break;
- case L'\b':
- std::wcout << '\\' << 'b';
- break;
- case L'\f':
- std::wcout << '\\' << 'f';
- break;
- case L'\n':
- std::wcout << '\\' << 'n';
- break;
- case L'\r':
- std::wcout << '\\' << 'r';
- break;
- case L'\t':
- std::wcout << '\\' << 't';
- break;
- default:
- if (ch < ' ')
- std::wcout << '\\' << 'u' << std::setfill(L'0') << std::setw(4) << std::hex << +ch;
- else
- {
- std::wcout << ch;
- if ((ch >= '0') & (ch <= '9') )
- number = 10 * number + (ch - '0');
- }
- }
- }
- return { size , number };
- }
- auto readDate(std::ifstream &fs)
- {
- int tm_year = read<int8_t>(fs) + 1900;
- int tm_mon = read<int8_t>(fs) + 1;
- int tm_mday = read<int8_t>(fs) + 1;
- std::wcout << '"' << tm_year << '-' << std::setfill(L'0') << std::setw(2) << tm_mon << '-' << std::setw(2) << tm_mday << '"';
- return 3;
- }
- auto readDateTime(std::ifstream &fs)
- {
- int tm_year = read<uint8_t>(fs) + 1900;
- int tm_mon = read<uint8_t>(fs) + 1;
- int tm_mday = read<uint8_t>(fs) + 1;
- int tm_hour = read<uint8_t>(fs);
- int tm_min = read<uint8_t>(fs);
- int tm_sec = read<uint8_t>(fs);
- fs.ignore(6);
- std::wcout << '"' << tm_year << '-' << std::setfill(L'0') << std::setw(2) << tm_mon << '-' << std::setw(2) << tm_mday << 'T' << std::setw(2) << tm_hour << ':' << std::setw(2) << tm_min << ':' << std::setw(2) << tm_sec << 'Z' << '"';
- return 12;
- }
- double readReal(std::ifstream &fs)
- {
- int exp = read<int8_t>(fs);
- auto sign = read<uint8_t>(fs);
- double mant = 0;
- double factor = 1;
- for (auto i = 0; i < 8; ++i)
- {
- auto hex = read<uint8_t>(fs);
- mant += factor * (10 * (hex >> 4) + (hex & 0xF));
- factor *= 100;
- }
- mant *= std::pow(10, exp - 15);
- if (sign & 0x80)
- {
- mant = -mant;
- }
- return mant;
- }
- size_t readAny(std::ifstream &fs, Type type, bool withType = false);
- auto readArray(std::ifstream &fs, Type type, bool withType = false)
- {
- auto num = read<uint16_t>(fs);
- fs.ignore(withType ? 2 : 0);
- size_t size = withType ? 4 : 2;
- std::wcout << '[';
- for (auto i = 0; i < num; ++i)
- {
- if (i)
- std::wcout << ',';
- size += readAny(fs, type);
- }
- std::wcout << ']';
- return size;
- }
- auto readRecord(std::ifstream &fs)
- {
- auto sw2 = false;
- auto size = read<uint32_t>(fs);
- auto foff = fs.tellg();
- auto tableId = read<uint16_t>(fs);
- read<uint16_t>(fs); //0x2036
- std::wcout << '{' << '"' << tableId << '"' << ':' << '{';
- for (auto fieldId = read<uint16_t>(fs); fieldId && !fs.eof(); fieldId = read<uint16_t>(fs))
- {
- if (sw2)
- std::wcout << ',';
- sw2 = true;
- auto type = Type(read<uint8_t>(fs));
- auto count = read<uint8_t>(fs);
- if (Field.count(fieldId))
- std::wcout << '"' << Field.at(fieldId) << '"' << ':';
- else
- std::wcout << '"' << fieldId << '"' << ':';
- if (count != 1)
- std::wcout << '[';
- for (auto i = 0; i < count; ++i)
- {
- if (i)
- std::wcout << ',';
- readAny(fs, type);
- }
- if (count != 1)
- std::wcout << ']';
- }
- auto recId = read<int64_t>(fs);
- auto ign = size - (fs.tellg() - foff);
- fs.ignore(ign);
- if (sw2)
- std::wcout << ',';
- std::wcout << L"\"RecId\":" << recId;
- std::wcout << '}' << '}';
- return size + 4;
- }
- auto readRecord2(std::ifstream &fs)
- {
- std::wcout << '{' << '"';
- auto size = read<uint32_t>(fs);
- auto foff = fs.tellg();
- auto tableSz = readString(fs);
- read<uint16_t>(fs); //0x2036
- std::wcout << '"' << ':' << '{' << '"';
- int number = 0;
- for (auto fieldSz = readString(fs); fieldSz.first > 2 && !fs.eof(); fieldSz = readString(fs))
- {
- number = fieldSz.second;
- auto type = Type(read<uint8_t>(fs));
- auto count = read<uint8_t>(fs);
- std::wcout << '"' << ':';
- if (count != 1)
- std::wcout << '[';
- for (auto i = 0; i < count; ++i)
- {
- if (i)
- std::wcout << ',';
- readAny(fs, type);
- }
- if (count != 1)
- std::wcout << ']';
- std::wcout << ',' << '"';
- if (count == 0)
- break;
- }
- for (auto i = 0; i < number; ++i)
- read<int32_t>(fs);
- auto recId = read<int64_t>(fs);
- auto ign = size - (fs.tellg() - foff);
- fs.ignore(ign);
- std::wcout << L"RecId\":" << recId;
- std::wcout << '}' << '}';
- return size + 4;
- }
- auto readContainer(std::ifstream &fs)
- {
- auto type = Type(read<uint8_t>(fs));
- auto sw2 = false;
- size_t size = 2;
- if (type == Type::Container)
- {
- type = Type(read<uint8_t>(fs));
- size += 2;
- }
- testEq(int(type), int(Type::Start));
- std::wcout << '[';
- for (type = Type(read<uint8_t>(fs)); type != Type::End && !fs.eof(); type = Type(read<uint8_t>(fs)))
- {
- if (sw2)
- std::wcout << ',';
- sw2 = true;
- size += 2 + readAny(fs, type, true);
- }
- size += 2;
- std::wcout << ']';
- return size;
- }
- size_t readAny(std::ifstream &fs, Type type, bool withType)
- {
- size_t size = 0;
- switch (type)
- {
- case Type::String:
- case Type::RString:
- case Type::VarString:
- std::wcout << '"';
- size = readString(fs).first;
- std::wcout << '"';
- break;
- case Type::Real:
- std::wcout << std::setprecision(16) << readReal(fs);
- return 10;
- case Type::Integer:
- std::wcout << read<int32_t>(fs);
- return 4;
- case Type::Int64:
- std::wcout << read<int64_t>(fs);
- return 8;
- case Type::Enum:
- return readEnum(fs, withType);
- case Type::EnumName:
- std::wcout << +read<uint8_t>(fs);
- return 1 + ignoreString(fs);
- case Type::Date:
- return readDate(fs);
- case Type::UtcDateTime:
- return readDateTime(fs);
- case Type::Guid:
- return readGuid(fs);
- case Type::Container:
- return readContainer(fs);
- case Type::StringArray:
- return readArray(fs, Type::String, true);
- case Type::IntArray:
- return readArray(fs, Type::Integer);
- case Type::Int64Array:
- return readArray(fs, Type::Int64);
- case Type::EnumArray:
- return readArray(fs, Type::Enum, true);
- case Type::DateArray:
- return readArray(fs, Type::Date);
- case Type::Record:
- return readRecord(fs);
- case Type::Record2:
- return readRecord2(fs);
- case Type::BLOB:
- std::wcout << L"\"!BLOB!\"";
- size = read<uint32_t>(fs);
- fs.ignore(size);
- size += 4;
- break;
- default:
- die("Unknown type " + std::to_string(int(type)));
- }
- return size;
- }
- auto read(std::ifstream &fs, bool sep)
- {
- auto size = read<uint32_t>(fs);
- if (size)
- {
- if (sep)
- std::wcout << ',' << '\n';
- auto type = Type(read<uint8_t>(fs));
- testEq(int(type), int(Type::Container));
- readContainer(fs);
- size += 4;
- }
- return size;
- }
- int main(int argc, char *argv[])
- {
- _setmode(_fileno(stdout), _O_U16TEXT);
- if (argc != 2)
- die("Usage: axbinaryreader file");
- std::ifstream fs(argv[1], std::ios::binary);
- if (fs.fail())
- die("Could not open file " + std::string(argv[1]));
- testEq(read<int64_t>(fs), 0x01174B9ADE);
- std::wcout << '[' << '\n';
- int count = 0;
- for (auto size = read(fs, false); size; size = read(fs, true))
- {
- ++count;
- }
- std::wcout << '\n' << ']'<< '\n';
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement