range_map: new container class for C++
Alright, there is now an update to the range_map container class template library. Some changes were made to increase allocator support. Here is the download:
http://beneficii.net/range_map.zip
Copy the folder "beneficii" into your C++ compiler's include folders. This library is header-only, so there are no .lib or .dll files to build. To use the range_map class, include it like so:
That is the only #include statement needed to access the range_map.
EDIT: Forgot to mention: range_map is in namespace beneficii.
Last edited by beneficii on 28 May 2014, 4:16 pm, edited 2 times in total.
If possible, I would like some help in writing good documentation for this class. I suck at writing documentation, like my poorly written documentation for my SMB3 Map Editor (less complex to write than this), which can be found here:
http://www.romhackin.../utilities/242/
A person I've known off and on over the years with the pseudonym z-byte went and wrote much improved documentation for the SMB3 Map Editor here, which I greatly appreciated:
http://pan.bytepub.com/map/
(Only thing that was off was mixing the sprites and airship retreat points section, but z-byte's description was much more effective than mine.)
If someone could help me with writing the documentation, I would greatly appreciate it.
Setting up website for range_map release (not completed yet):
http://beneficii.net/range_map/
Note that none of the links other than the two zip files work yet. Still, it hopefully gives an overview and I wonder if anyone has any feedback on how to best describe these functions.
EDIT: Also, note that these new range_map container class templates have changed features from before.
Did some cleaning up and added two files, the one for value_type and the other for range_map_item. I also fixed a bug in the range_map container.
Hi! Any generic class or algorithm that integrates well with STL is interesting, if not else, then for an exercise. (I, for one, wrote a vector that does not use heap allocation if there are few items.) I think the lack of feedback is because we don't see in which practical cases it is useful. In what kind of algorithm would you use it?
_________________
Maths student. Somewhere between NT and ASD.
In something similar to an XML document, as it "nests" sub-ranges within their parent ranges, where you need file location and lengths to be kept track of.
When I built this library, I had in mind to use it as part of an interactive disassembler. For example, let's say we have $30 ($ = hex) bytes of data, but we want to group them into rows. Well, we could come up with code like this:
public:
data_byte_rows(unsigned long num_per_row) : num_per_row(num_per_row) {}
void init_printing() const {current_position = 0;}
bool finished(unsigned long length) const {return current_position >= length;}
std::string print(unsigned long fileaddr, unsigned long length) const {
if(finished(length)) return "";
std::string ret = ".BYTE ";
for(unsigned long u = current_position; u < num_per_row && u < length; ++u) {
if(u > current_position) ret += ", ";
ret += byte_to_string(fileaddr + u, rdxHEX);
}
current_position = u;
return ret;
}
private:
unsigned long num_per_row;
mutable unsigned long current_position;
};
void some_function() {
beneficii::range_map<unsigned long, data_byte_rows> rm;
rm.emplace(true, 0xa007, 0xa007 + 0x30, 10)
auto i = rm.begin();
i->mapped.init_printing();
while(!i->mapped.finished()) {
std::cout << i->mapped.print(i->left_pt(), i->width()) << std::endl;
}
)
This would produce 5 rows of .BYTE starting at file address $A007, the first 4 having 10 bytes printed each, and the 5th having 8 bytes printed. This would save you from having 48 rows with a single byte each, and allow you to make a more readable disassembly.
You could store a whole bunch of them; with the prevention of overlap, you can avoid conflicts. You could perhaps have many of these class types with the same base that are stored together (and nest within each other, etc.), using names to determine which derived class you're working with.
In this way, it's a little like an XML document, no?
I've posted an updated sample.
One idea I have in mind is to write an allocator that does factory construction as needed. I think that would work well with the base class being stored, which could be one of many derived types--which one would be discovered by its name.
Hobby.
Anyway, this would be one implementation of range_map, though this is just the header file(s):
#define CLASSES_H
#include <string>
#include <vector>
#include <memory>
#include <beneficii/range_map/range_map>
#include <wx/xml/xml.h>
#include "master.h"
typedef unsigned long dword;
typedef unsigned short word;
typedef unsigned char byte;
enum class RADICES : byte {
rdxBIN = 2,
rdxDEC = 10,
rdxHEX = 16
};
enum class COLUMNS : byte {
colFILEADDR = 0,
colMEMADDR = 1,
colLABELS = 2,
colDIRECTIVES = 3,
colARGUMENTS = 4,
colCOMMENTS = 5,
colSHARELINE = 128
};
enum class FILETYPE : byte {
ftySOURCE;
ftyBINARY;
};
struct output_data {
COLUMNS column;
std::string text;
};
class disasm_position {
dword fileaddr;
word position;
};
struct disasm_position_comparator : std::binary_function<disasm_position, disasm_position, bool> {
bool operator()(const disasm_position& a, const disasm_position& b) {
if(a.fileaddr < b.fileaddr) return true;
if(b.fileaddr < a.fileaddr) return false;
return a.nesting < b.nesting);
}
};
template<class T>
class factory_allocator<T> {
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<class U>
struct rebind<U> {
typedef factory_allocator<U> other;
};
factory_allocator();
pointer address(reference) const;
const_pointer address(const_reference) const;
pointer allocate(size_type);
void deallocate(pointer);
size_type max_type() const;
void construct(pointer, wxXmlNode*); //factory construction of object
void destroy(pointer);
private:
disasm_position last;
};
class disasm_base;
typedef beneficii::range_map<disasm_position, std::unique_ptr<disasm_base>, disasm_position_comparator,
factory_allocator<range_map_item<disasm_position, std::unique_ptr<disasm_base>>> rm_disasm;
class disasm_base {
public:
disasm_base(dword fileaddr);
dword get_fileaddr() const;
virtual std::string get_class_name() const = 0;
virtual bool advances_thru_file() const = 0;
bool init() const;
virtual bool finished() const = 0;
virtual void get_output(std::vector<output_data>&) const = 0;
virtual wxXmlNode* get_xml() const = 0;
protected:
dword fileaddr;
mutable word index;
};
class disasm_noadv_base : public disasm_base {
public:
disasm_noadv_base(dword fileaddr);
bool advances_thru_file() const; //false
};
class comments_base : public disasm_noadv_base {
public:
comments_base(dword fileaddr, std::string&& comments);
bool finished() const;
virtual void parse_input_string() = 0;
std::string get_comments() const;
protected:
std::string comments;
};
class row_arrays_base {
public:
row_arrays_base(byte max_row_length);
byte get_max_row_length();
protected:
byte max_row_length;
};
class standalone_comments : public comments_base, public row_arrays_base {
public:
standalone_comments(dword fileaddr, std::string&& comments, byte max_row_length);
std::string get_class_name() const; //"standalone comments"
void parse_input_string();
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class sameline_comments : public comments_base {
public:
standalone_comments(dword fileaddr, std::string&& comments);
std::string get_class_name() const; //"sameline_comments"
void parse_input_string();
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class identifiers_base {
identifiers_base(std::string&& identifier);
std::string get_identifier() const;
protected:
std::string identifier;
};
class labels_base : public disasm_noadv_base, public identifiers_base {
labels_base(dword fileaddr, std::string&& identifier);
};
class standalone_label : public labels_base {
public:
standalone_label(dword fileaddr, std::string&& identifier);
std::string get_class_name() const; //"standalone_label"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class sameline_label : public labels_base {
public:
sameline_label(dword fileaddr, std::string&& identifier);
std::string get_class_name() const; //"sameline_label"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class radices_base {
radices_base(RADICES radix);
RADICES get_radix() const;
std::string get_value_str(long value, byte minimum_length) const;
std::string get_value_str(dword value, byte minimum_length) const;
std::string get_value_str(word value, byte minimum_length) const;
std::string get_value_str(byte value, byte minimum_length) const;
protected:
RADICES radix;
};
class values_base : public radices_base {
public:
values_base(word value, RADICES radix);
word get_value() const;
protected:
word value;
};
class alttext_base {
public:
alttext_base(std::string&& alttext);
bool check_against_value(long value);
protected:
std::string alttext;
};
class base : public disasm_noadv_base, public values_base, public alttext_base {
public:
base(std::string&& identifier, word value, RADICES radix, std::string&& alttext);
std::string get_class_name() const; //"base"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class equate : public disasm_noadv_base, public identifiers_base, public values_base, public alttext_base {
public:
equate(std::string&& identifier, word value, RADICES radix, std::string&& alttext);
std::string get_class_name() const; //"equate"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class disasm_adv_base : public disasm_base {
public:
disasm_adv_base(dword fileaddr, word length);
bool advances_thru_file() const; //true
word get_length() const;
void pass_iterator(rm_disasm::const_iterator);
protected:
void notify_adv(word length) const;
rm_disasm::const_iterator iter;
word length;
};
class files_base : public disasm_adv_base {
public:
files_base(dword fileaddr, word length, std::string&& filename);
std::string get_filename() const;
protected:
std::string filename;
};
class file_incsrc : public files_base {
public:
file_incsrc(dword fileaddr, word length, std::string&& filename);
std::string get_class_name() const; //"file_incsrc"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class file_incbin : public files_base {
public:
file_incbin(dword fileaddr, word length, std::string&& filename);
std::string get_class_name() const; //"file_incbin"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_arrays_base : public disasm_adv_base, public radices_base, public row_arrays_base {
public:
data_arrays_base(dword fileaddr, word length, RADICES radix, byte max_row_length);
bool finished() const;
};
class data_byte_array : public data_arrays_base {
public:
data_byte_array(dword fileaddr, word length, RADICES radix, word row_length, byte max_row_length);
std::string get_class_name() const; //"data_byte_array"
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_word_array : public data_arrays_base {
public:
data_word_array(dword fileaddr, word length, RADICES radix, byte max_row_length);
word get_length_in_words() const;
std::string get_class_name() const; //"data_word_array"
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_hibyte_array : public data_arrays_base {
public:
data_hibyte_array(dword fileaddr, word length, RADICES radix, byte max_row_length);
std::string get_class_name() const; //"data_hibyte_array"
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_lobyte_array : public data_arrays_base {
public:
data_lobyte_array(dword fileaddr, word length, RADICES radix, byte max_row_length);
std::string get_class_name() const; //"data_lobyte_array"
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_space_bytes : public disasm_adv_base, public alttext_base, public radices_base {
public:
data_space_bytes(dword fileaddr, word length, std::string&& alttext, RADICES radix);
std::string get_class_name() const; //"data_space_bytes"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_space_words : public disasm_adv_base, public alttext_base, public radices_base {
public:
data_space_words(dword fileaddr, word length, std::string&& alttext, RADICES radix);
word get_length_in_words() const;
std::string get_class_name() const; //"data_space_words"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_align : public disasm_adv_base, public alttext_base, public radices_base {
public:
data_align(dword fileaddr, RADICES radix, std::string&& alttext, word alignment_boundary);
std::string get_class_name() const; //"data_align"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
class data_pad : public disasm_adv_base, public alttext_base, public radices_base {
public:
data_align(dword fileaddr, std::string&& alttext,
RADICES radix, word termination_point);
std::string get_class_name() const; //"data_pad"
bool finished() const;
void get_output(std::vector<output_data>&) const;
wxXmlNode* get_xml() const;
};
#endif
| Similar Topics | |
|---|---|
| Class Size for an Autism Specific Class - Survey |
21 Dec 2010, 1:37 pm |
| Friendship class or Social Skills class - do they help? |
08 Mar 2011, 10:31 pm |
| Canadian middle class wealthier than American middle class |
04 May 2014, 7:51 am |
| In class, is everyone against you? |
06 Sep 2006, 4:14 pm |
