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