-
Notifications
You must be signed in to change notification settings - Fork 1
/
intelhex.h
135 lines (97 loc) · 3.74 KB
/
intelhex.h
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once
#include <cstdint>
#include <optional>
#include <map>
#include <variant>
#include <vector>
#include <string>
#include <fstream>
class IntelHex
{
public:
using Addr = uint32_t;
using OptionalAddr = std::optional<Addr>;
using BinArray = std::vector<uint8_t>;
IntelHex() {}
IntelHex(const std::string &fileName)
{ loadhex(fileName); }
IntelHex(std::istream & file)
{ loadhex(file); }
IntelHex(std::initializer_list<std::pair<Addr, uint8_t> > init)
{ for (auto & i : init) buf[i.first] = i.second; }
void loadhex(std::istream &file);
void loadhex(const std::string &fileName)
{ std::ifstream f(fileName); loadhex(f); }
void loadbin(std::istream &file, Addr offset=0);
void loadbin(const std::string &fileName, Addr offset=0)
{ std::ifstream f(fileName); loadbin(f, offset); }
void frombytes(const BinArray &bytes, Addr offset=0);
// Return binary array
BinArray tobinarray(OptionalAddr start = {}, OptionalAddr end = {}, OptionalAddr size = {}) const;
// Convert to binary and write to file
void tobinfile(std::ostream & file, OptionalAddr start = {}, OptionalAddr end = {}, OptionalAddr size = {}) const;
void tobinfile(const std::string & fileName, OptionalAddr start = {}, OptionalAddr end = {}, OptionalAddr size = {}) const;
// Returns all used addresses in sorted order
std::vector<Addr> addresses() const;
// Get minimal address of HEX content.
OptionalAddr minaddr() const;
// Get maximal address of HEX content.
OptionalAddr maxaddr() const;
uint8_t operator[](Addr addr) const
{
auto it = buf.find(addr);
return (it != buf.end()) ? it->second : padding;
}
// uint8_t & operator[](Addr addr)
// { return buf[addr]; }
void add(Addr addr, uint8_t data)
{ buf.insert_or_assign(addr, data); }
void del(Addr addr)
{ buf.erase(addr); }
size_t size() const
{ return buf.size(); }
// Write data to file in HEX format
void write_hex_file(std::ostream & file, bool write_start_addr=true, uint32_t byte_count=16) const;
void write_hex_file(const std::string & fileName, bool write_start_addr=true, uint32_t byte_count=16) const;
enum class Overlap {
error, ignore, replace
};
void merge(const IntelHex & other, Overlap overlap=Overlap::error);
uint8_t padding = 0xFF;
struct StartAddrSegmented {
uint16_t CS;
uint16_t IP;
};
struct StartAddrExtended {
uint32_t EIP;
};
using StartAddr = std::optional< std::variant<StartAddrSegmented, StartAddrExtended> >;
StartAddr start_addr;
// Return a list of ordered tuple objects, representing contiguous occupied data addresses.
// Each tuple has a length of two and follows the semantics of the range and xrange objects.
// The second entry of the tuple is always an integer greater than the first entry.
struct Segment {
Addr begin;
Addr end;
};
std::vector<Segment> segments();
private:
std::map<Addr, uint8_t> buf;
uint32_t offset = 0;
bool decode_record(std::string s, uint32_t line=0);
std::pair<OptionalAddr, OptionalAddr>
get_start_end(OptionalAddr start = {}, OptionalAddr end = {}, OptionalAddr size = {}) const;
static BinArray unhexlify(const std::string& input);
static std::string hexlify(const BinArray& bin);
};
// some helpers
inline bool operator==(const IntelHex::StartAddr & a, const IntelHex::StartAddr & b)
{
if (a.has_value() && b.has_value())
return (a.value() == b.value());
return (a.has_value() == b.has_value());
};
inline bool operator==(const IntelHex::StartAddrExtended & a, const IntelHex::StartAddrExtended & b)
{ return a.EIP == b.EIP; };
inline bool operator==(const IntelHex::StartAddrSegmented & a, const IntelHex::StartAddrSegmented & b)
{ return (a.CS == b.CS) && (a.IP == b.IP); };