aboutsummaryrefslogtreecommitdiff
path: root/libs/esptk/src/subrecord.cpp
blob: cb3890a561c790a72dcd3b0933c41e33d0961fd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "subrecord.h"
#include "espexceptions.h"
#include "esptypes.h"
#include <cstdint>
#include <cstring>
#include <string>
#include <unordered_map>

ESP::SubRecord::SubRecord() : m_Type(TYPE_UNKNOWN), m_Data() {}

bool ESP::SubRecord::readFrom(std::istream& stream, uint32_t sizeOverride)
{
  static std::unordered_map<std::string, EType> s_TypeMap{{"HEDR", TYPE_HEDR},
                                                          {"CNAM", TYPE_CNAM},
                                                          {"MAST", TYPE_MAST},
                                                          {"ONAM", TYPE_ONAM},
                                                          {"SNAM", TYPE_SNAM}};

  char typeString[5];
  if (!stream.read(typeString, 4)) {
    if (stream.gcount() == 0) {
      return false;
    } else {
      throw ESP::InvalidRecordException("sub-record incomplete (unknown type)");
    }
  }
  if (stream.gcount() != 4) {
    throw ESP::InvalidRecordException(
        std::string("sub-record type incomplete (invalid type ") + typeString + ")");
  }
  typeString[4] = '\0';  // not sure if this is required, shouldn't be
  auto iter     = s_TypeMap.find(std::string(typeString));
  if (iter != s_TypeMap.end()) {
    m_Type = iter->second;
  } else if (strncmp(typeString, "XXXX", 4) == 0) {
    if (readType<uint16_t>(stream) != 4) {
      throw ESP::InvalidRecordException(
          "XXXX record is supposed to be 4 bytes in size");
    }
    return readFrom(stream, readType<uint32_t>(stream));
  } else {
    m_Type = TYPE_UNKNOWN;
  }

  uint32_t dataSize = readType<uint16_t>(stream);
  if (sizeOverride != 0UL) {
    dataSize = sizeOverride;
  }
  m_Data.resize(dataSize);

  if (dataSize > 0) {
    stream.read(reinterpret_cast<char*>(m_Data.data()), dataSize);
  }
  if (!stream) {
    throw ESP::InvalidRecordException(std::string("sub-record incomplete: ") +
                                      typeString);
  }
  return true;
}