1 #include "bufferview.h"
2 #include "../../support/utils.h"
3 #include <cctype>
4
5 namespace REDasm {
6 namespace Buffer {
7
8 const std::string BufferView::WILDCARD_BYTE = "??";
9
BufferView()10 BufferView::BufferView(): m_buffer(nullptr), m_offset(0), m_size(0) { }
BufferView(const AbstractBuffer * buffer,u64 offset,u64 size)11 BufferView::BufferView(const AbstractBuffer *buffer, u64 offset, u64 size): m_buffer(buffer), m_offset(offset), m_size(size) { }
12
view(u64 offset,u64 size) const13 BufferView BufferView::view(u64 offset, u64 size) const
14 {
15 if(!size)
16 size = m_size - offset;
17
18 if(offset >= m_size)
19 throw std::out_of_range("Buffer:slice(): offset out of bounds");
20
21 return BufferView(m_buffer, m_offset + offset, size);
22 }
23
operator [](size_t idx) const24 u8 BufferView::operator[](size_t idx) const
25 {
26 if(idx >= m_size)
27 throw std::out_of_range("Buffer::operator[]: index is out of range");
28
29 return this->data()[idx];
30 }
31
operator [](size_t idx)32 u8 &BufferView::operator[](size_t idx)
33 {
34 if(idx >= m_size)
35 throw std::out_of_range("Buffer::operator[]: index is out of range");
36
37 return this->data()[idx];
38 }
39
operator ++()40 BufferView &BufferView::operator++()
41 {
42 if(!m_size)
43 throw std::out_of_range("Buffer:operator++(): reached end of buffer");
44
45 m_offset++;
46 m_size--;
47 return *this;
48 }
49
operator ++(int)50 BufferView BufferView::operator ++(int)
51 {
52 if(!m_size)
53 throw std::out_of_range("Buffer:operator++(int): reached end of buffer");
54
55 BufferView ret(m_buffer, m_offset, m_size);
56 m_offset++;
57 m_size--;
58 return ret;
59 }
60
copyTo(AbstractBuffer * buffer)61 void BufferView::copyTo(AbstractBuffer *buffer)
62 {
63 if(buffer->size() < m_size)
64 buffer->resize(m_size);
65
66 std::copy_n(this->data(), m_size, buffer->data());
67 }
68
toString() const69 std::string BufferView::toString() const { return std::string(reinterpret_cast<const char*>(this->data()), this->size()); }
resize(u64 size)70 void BufferView::resize(u64 size) { m_size = std::min(size, m_buffer->size()); }
patternLength(const std::string & pattern) const71 size_t BufferView::patternLength(const std::string &pattern) const { return pattern.size() / 2; }
72
patternRange(std::string & pattern,u64 & startoffset,u64 & endoffset,u64 & beginoffset) const73 std::pair<u8, u8> BufferView::patternRange(std::string &pattern, u64 &startoffset, u64 &endoffset, u64& beginoffset) const
74 {
75 std::pair<u8, u8> bp;
76
77 for(size_t i = 0; i < pattern.size() - 2; i += 2)
78 {
79 std::string hexb = pattern.substr(i, 2);
80
81 if(hexb == BufferView::WILDCARD_BYTE)
82 continue;
83
84 pattern = pattern.substr(i); // Trim leading wildcards
85 REDasm::byte(hexb, &bp.first);
86 beginoffset = i / 2;
87 startoffset += i / 2;
88 break;
89 }
90
91 for(s64 i = pattern.size() - 2; i >= 0; i -= 2)
92 {
93 std::string hexb = pattern.substr(i, 2);
94
95 if(hexb == BufferView::WILDCARD_BYTE)
96 continue;
97
98 pattern = pattern.substr(0, i); // Trim trailing wildcards
99 REDasm::byte(hexb, &bp.second);
100 endoffset = startoffset + (i / 2);
101 break;
102 }
103
104 return bp;
105 }
106
comparePattern(const std::string & pattern,const u8 * pdata) const107 bool BufferView::comparePattern(const std::string &pattern, const u8 *pdata) const
108 {
109 const u8* pcurr = pdata;
110
111 for(size_t i = 0; i < pattern.size() - 2; i += 2, pcurr++)
112 {
113 std::string hexb = pattern.substr(i, 2);
114
115 if(hexb == BufferView::WILDCARD_BYTE)
116 continue;
117
118 u8 b = 0;
119
120 if(!REDasm::byte(hexb, &b) || (b != *pcurr))
121 return false;
122 }
123
124 return true;
125 }
126
preparePattern(std::string & pattern) const127 bool BufferView::preparePattern(std::string &pattern) const
128 {
129 if(this->eob() || pattern.empty())
130 return false;
131
132 pattern.erase(std::remove_if(pattern.begin(), pattern.end(), ::isspace), pattern.end());
133
134 if((pattern.size() % 2) || (this->patternLength(pattern) > this->size()))
135 return false;
136
137 size_t wccount = 0;
138
139 for(size_t i = 0; i < pattern.size() - 2; i += 2)
140 {
141 std::string hexb = pattern.substr(i, 2);
142
143 if(hexb == BufferView::WILDCARD_BYTE)
144 {
145 wccount++;
146 continue;
147 }
148
149 if(!std::isxdigit(hexb.front()) || !std::isxdigit(hexb.back()))
150 return false;
151 }
152
153 return wccount < pattern.size();
154 }
155
156 } // namespace Buffer
157 } // namespace REDasm
158