#ifndef __HEXFILE_H__ #define __HEXFILE_H__ #include class HexFile { public: struct Reader { const char *top_char, *last_char; Reader(const char *top, const char *last) : top_char(top), last_char(last){}; ~Reader(){} struct content_t { unsigned long address; unsigned char buf[0xFF]; int buf_valid; }; class iterator : public std::iterator< input_iterator_tag, content_t> { protected: static unsigned int hex2uint(char *c, int length){ unsigned int res(0); for(int i(0); i < length; ++i, ++c){ res <<= 4; if(((*c) >= 'A') && ((*c) <= 'F')){ res += ((*c - 'A') + 10); }else if(((*c) >= 'a') && ((*c) <= 'f')){ res += ((*c - 'a') + 10); }else{ res += (*c - '0'); } } return res; } char *first_char; int remain; unsigned int global_offset_address; content_t parsed_info; int parse_motorola(){ char *current(first_char + 1); int record_type((*current) - '0'); if((record_type < 1) || (record_type > 3)){ return 0; } unsigned int record_length(hex2uint(++current, 2)); current += 2; unsigned int checksum(record_length); unsigned int address_bytes(record_type + 1); parsed_info.address = hex2uint(current, address_bytes * 2); current += (address_bytes * 2); for(unsigned long addr(parsed_info.address); addr > 0; addr >>= 8){ checksum += addr; // last 2 hexes are important } // extract data int pure_data_length(record_length - address_bytes - 1); for(int i(0); i < pure_data_length; ++i){ parsed_info.buf[i] = (unsigned char)hex2uint(current, 2); current += 2; checksum += parsed_info.buf[i]; } // validate using checksum checksum += hex2uint(current, 2); return ((checksum & 0xFF) == 0xFF) ? pure_data_length : 0; } int parse_intel(){ char *current(first_char + 1); int pure_data_length(hex2uint(current, 2)); current += 2; unsigned int checksum(pure_data_length); int offset_address(hex2uint(current, 4)); current += 4; checksum += offset_address; checksum += (offset_address >> 8); parsed_info.address = offset_address + global_offset_address; int record_type(hex2uint(current, 2)); current += 2; checksum += record_type; for(int i(0); i < pure_data_length; ++i){ parsed_info.buf[i] = (unsigned char)hex2uint(current, 2); current += 2; checksum += parsed_info.buf[i]; } checksum += hex2uint(current, 2); switch(record_type){ case 0: break; case 2: // segment address record case 4: // extended linear address field if((offset_address == 0) && (pure_data_length == 2) && ((checksum & 0xFF) == 0x00)){ global_offset_address = parsed_info.buf[0]; global_offset_address <<= 8; global_offset_address |= parsed_info.buf[1]; global_offset_address <<= ((record_type == 4) ? 16 : 4); } default: return 0; } return ((checksum & 0xFF) == 0x00) ? pure_data_length : 0; } void parse(){ parsed_info.buf_valid = 0; if(remain == 0){return;} switch(*first_char){ case 'S': parsed_info.buf_valid = parse_motorola(); break; case ':': parsed_info.buf_valid = parse_intel(); break; } } public: iterator(char *buf, int length) : first_char(buf), remain(length), global_offset_address(0), parsed_info() {parse();} iterator(char *c) : first_char(c), remain(0), global_offset_address(0), parsed_info() {} iterator(const iterator &orig) : first_char(orig.first_char), remain(orig.remain), global_offset_address(orig.global_offset_address), parsed_info(orig.parsed_info) {} ~iterator() {} iterator& operator++() { bool found_tail(false); while(remain){ --remain; ++first_char; if(((*first_char) == '\r') || ((*first_char) == '\n')){ found_tail = true; continue; } if(found_tail){break;} } parse(); return *this; } iterator operator++(int) { iterator cpy(*this); operator++(); return cpy; } bool operator==(const iterator& rhs) const { return first_char == rhs.first_char; } bool operator!=(const iterator& rhs) const { return first_char != rhs.first_char; } const content_t& operator*() const { return parsed_info; } const content_t* operator->() const { return &parsed_info; } }; iterator begin() const { return iterator(const_cast(top_char), last_char - top_char); } iterator end() const { return iterator(const_cast(last_char)); } }; }; #endif /* __HEXFILE_H__ */