mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2025-06-08 02:12:40 +08:00
Rename lists internally.
This commit is contained in:
parent
363bf4e00d
commit
6d7ec87ee8
@ -33,59 +33,57 @@ namespace tesseract {
|
|||||||
* Generic list class for singly linked CONS cell lists
|
* Generic list class for singly linked CONS cell lists
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
template <typename CLASSNAME>
|
template <typename T>
|
||||||
class CLIST {
|
class ConsList {
|
||||||
friend class LINK;
|
friend class Link;
|
||||||
//friend class ITERATOR;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* CLASS - LINK
|
* CLASS - Link
|
||||||
*
|
*
|
||||||
* Generic link class for singly linked CONS cell lists
|
* Generic link class for singly linked CONS cell lists
|
||||||
*
|
*
|
||||||
* Note: No destructor - elements are assumed to be destroyed EITHER after
|
* Note: No destructor - elements are assumed to be destroyed EITHER after
|
||||||
* they have been extracted from a list OR by the CLIST destructor which
|
* they have been extracted from a list OR by the ConsList destructor which
|
||||||
* walks the list.
|
* walks the list.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
struct LINK {
|
struct Link {
|
||||||
LINK *next{};
|
Link *next{};
|
||||||
CLASSNAME *data{};
|
T *data{};
|
||||||
|
|
||||||
LINK() = default;
|
Link() = default;
|
||||||
LINK(const LINK &) = delete;
|
Link(const Link &) = delete;
|
||||||
void operator=(const LINK &) = delete;
|
void operator=(const Link &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLASS - ITERATOR
|
* CLASS - Iterator
|
||||||
*
|
*
|
||||||
* Generic iterator class for singly linked lists with embedded
|
* Generic iterator class for singly linked lists with embedded
|
||||||
*links
|
*links
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
class ITERATOR {
|
class Iterator {
|
||||||
CLIST *list; // List being iterated
|
ConsList *list; // List being iterated
|
||||||
LINK *prev; // prev element
|
Link *prev; // prev element
|
||||||
LINK *current; // current element
|
Link *current; // current element
|
||||||
LINK *next; // next element
|
Link *next; // next element
|
||||||
LINK *cycle_pt; // point we are cycling the list to.
|
Link *cycle_pt; // point we are cycling the list to.
|
||||||
bool ex_current_was_last; // current extracted was end of list
|
bool ex_current_was_last; // current extracted was end of list
|
||||||
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
||||||
bool started_cycling; // Have we moved off the start?
|
bool started_cycling; // Have we moved off the start?
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::extract_sublist()
|
* Iterator::extract_sublist()
|
||||||
*
|
*
|
||||||
* This is a private member, used only by CLIST::assign_to_sublist.
|
* This is a private member, used only by ConsList::assign_to_sublist.
|
||||||
* Given another iterator for the same list, extract the links from THIS to
|
* Given another iterator for the same list, extract the links from THIS to
|
||||||
* OTHER inclusive, link them into a new circular list, and return a
|
* OTHER inclusive, link them into a new circular list, and return a
|
||||||
* pointer to the last element.
|
* pointer to the last element.
|
||||||
* (Can't inline this function because it contains a loop)
|
* (Can't inline this function because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
LINK *extract_sublist( // from this current
|
Link *extract_sublist( // from this current
|
||||||
ITERATOR *other_it) { // to other current
|
Iterator *other_it) { // to other current
|
||||||
ITERATOR temp_it = *this;
|
Iterator temp_it = *this;
|
||||||
|
|
||||||
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -93,12 +91,12 @@ public:
|
|||||||
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
||||||
|
|
||||||
if (list != other_it->list)
|
if (list != other_it->list)
|
||||||
BAD_EXTRACTION_PTS.error("ITERATOR.extract_sublist", ABORT);
|
BAD_EXTRACTION_PTS.error("Iterator.extract_sublist", ABORT);
|
||||||
if (list->empty())
|
if (list->empty())
|
||||||
EMPTY_LIST.error("ITERATOR::extract_sublist", ABORT);
|
EMPTY_LIST.error("Iterator::extract_sublist", ABORT);
|
||||||
|
|
||||||
if (!current || !other_it->current)
|
if (!current || !other_it->current)
|
||||||
DONT_EXTRACT_DELETED.error("ITERATOR.extract_sublist", ABORT);
|
DONT_EXTRACT_DELETED.error("Iterator.extract_sublist", ABORT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ex_current_was_last = other_it->ex_current_was_last = false;
|
ex_current_was_last = other_it->ex_current_was_last = false;
|
||||||
@ -108,7 +106,7 @@ public:
|
|||||||
temp_it.mark_cycle_pt();
|
temp_it.mark_cycle_pt();
|
||||||
do { // walk sublist
|
do { // walk sublist
|
||||||
if (temp_it.cycled_list()) { // can't find end pt
|
if (temp_it.cycled_list()) { // can't find end pt
|
||||||
BAD_SUBLIST.error("ITERATOR.extract_sublist", ABORT);
|
BAD_SUBLIST.error("Iterator.extract_sublist", ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp_it.at_last()) {
|
if (temp_it.at_last()) {
|
||||||
@ -146,28 +144,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ITERATOR() { // constructor
|
Iterator() { // constructor
|
||||||
list = nullptr;
|
list = nullptr;
|
||||||
} // unassigned list
|
} // unassigned list
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::ITERATOR
|
* Iterator::Iterator
|
||||||
*
|
*
|
||||||
* CONSTRUCTOR - set iterator to specified list;
|
* CONSTRUCTOR - set iterator to specified list;
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
ITERATOR( // constructor
|
Iterator( // constructor
|
||||||
CLIST *list_to_iterate) {
|
ConsList *list_to_iterate) {
|
||||||
set_to_list(list_to_iterate);
|
set_to_list(list_to_iterate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::set_to_list
|
* Iterator::set_to_list
|
||||||
*
|
*
|
||||||
* (Re-)initialise the iterator to point to the start of the list_to_iterate
|
* (Re-)initialise the iterator to point to the start of the list_to_iterate
|
||||||
* over.
|
* over.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void set_to_list( // change list
|
void set_to_list( // change list
|
||||||
CLIST *list_to_iterate) {
|
ConsList *list_to_iterate) {
|
||||||
list = list_to_iterate;
|
list = list_to_iterate;
|
||||||
prev = list->last;
|
prev = list->last;
|
||||||
current = list->First();
|
current = list->First();
|
||||||
@ -179,20 +177,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_after_then_move
|
* Iterator::add_after_then_move
|
||||||
*
|
*
|
||||||
* Add a new element to the list after the current element and move the
|
* Add a new element to the list after the current element and move the
|
||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_then_move( // add after current &
|
void add_after_then_move( // add after current &
|
||||||
CLASSNAME *new_data) {
|
T *new_data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
BAD_PARAMETER.error("ITERATOR::add_after_then_move", ABORT, "new_data is nullptr");
|
BAD_PARAMETER.error("Iterator::add_after_then_move", ABORT, "new_data is nullptr");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto new_element = new LINK;
|
auto new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
|
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
@ -222,20 +220,20 @@ public:
|
|||||||
} // move to new
|
} // move to new
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_after_stay_put
|
* Iterator::add_after_stay_put
|
||||||
*
|
*
|
||||||
* Add a new element to the list after the current element but do not move
|
* Add a new element to the list after the current element but do not move
|
||||||
* the iterator to the new element.
|
* the iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_stay_put( // add after current &
|
void add_after_stay_put( // add after current &
|
||||||
CLASSNAME *new_data) {
|
T *new_data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
BAD_PARAMETER.error("ITERATOR::add_after_stay_put", ABORT, "new_data is nullptr");
|
BAD_PARAMETER.error("Iterator::add_after_stay_put", ABORT, "new_data is nullptr");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto new_element = new LINK;
|
auto new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
|
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
@ -267,20 +265,20 @@ public:
|
|||||||
} // stay at current
|
} // stay at current
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_before_then_move
|
* Iterator::add_before_then_move
|
||||||
*
|
*
|
||||||
* Add a new element to the list before the current element and move the
|
* Add a new element to the list before the current element and move the
|
||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_then_move( // add before current &
|
void add_before_then_move( // add before current &
|
||||||
CLASSNAME *new_data) {
|
T *new_data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
BAD_PARAMETER.error("ITERATOR::add_before_then_move", ABORT, "new_data is nullptr");
|
BAD_PARAMETER.error("Iterator::add_before_then_move", ABORT, "new_data is nullptr");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto new_element = new LINK;
|
auto new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
|
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
@ -306,20 +304,20 @@ public:
|
|||||||
} // move to new
|
} // move to new
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_before_stay_put
|
* Iterator::add_before_stay_put
|
||||||
*
|
*
|
||||||
* Add a new element to the list before the current element but don't move the
|
* Add a new element to the list before the current element but don't move the
|
||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_stay_put( // add before current &
|
void add_before_stay_put( // add before current &
|
||||||
CLASSNAME *new_data) {
|
T *new_data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
BAD_PARAMETER.error("ITERATOR::add_before_stay_put", ABORT, "new_data is nullptr");
|
BAD_PARAMETER.error("Iterator::add_before_stay_put", ABORT, "new_data is nullptr");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto new_element = new LINK;
|
auto new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
|
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
@ -346,14 +344,14 @@ public:
|
|||||||
} // stay at current
|
} // stay at current
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_list_after
|
* Iterator::add_list_after
|
||||||
*
|
*
|
||||||
* Insert another list to this list after the current element but don't move
|
* Insert another list to this list after the current element but don't move
|
||||||
*the
|
*the
|
||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_after( // add a list &
|
void add_list_after( // add a list &
|
||||||
CLIST *list_to_add) {
|
ConsList *list_to_add) {
|
||||||
if (!list_to_add->empty()) {
|
if (!list_to_add->empty()) {
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
list->last = list_to_add->last;
|
list->last = list_to_add->last;
|
||||||
@ -384,14 +382,14 @@ public:
|
|||||||
} // stay at current
|
} // stay at current
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_list_before
|
* Iterator::add_list_before
|
||||||
*
|
*
|
||||||
* Insert another list to this list before the current element. Move the
|
* Insert another list to this list before the current element. Move the
|
||||||
* iterator to the start of the inserted elements
|
* iterator to the start of the inserted elements
|
||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_before( // add a list &
|
void add_list_before( // add a list &
|
||||||
CLIST *list_to_add) {
|
ConsList *list_to_add) {
|
||||||
if (!list_to_add->empty()) {
|
if (!list_to_add->empty()) {
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
list->last = list_to_add->last;
|
list->last = list_to_add->last;
|
||||||
@ -419,33 +417,33 @@ public:
|
|||||||
}
|
}
|
||||||
} // move to it 1st item
|
} // move to it 1st item
|
||||||
|
|
||||||
CLASSNAME *data() { // get current data
|
T *data() { // get current data
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ITERATOR::data", ABORT);
|
NO_LIST.error("Iterator::data", ABORT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return current->data;
|
return current->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::data_relative
|
* Iterator::data_relative
|
||||||
*
|
*
|
||||||
* Return the data pointer to the element "offset" elements from current.
|
* Return the data pointer to the element "offset" elements from current.
|
||||||
* "offset" must not be less than -1.
|
* "offset" must not be less than -1.
|
||||||
* (This function can't be INLINEd because it contains a loop)
|
* (This function can't be INLINEd because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *data_relative( // get data + or - ...
|
T *data_relative( // get data + or - ...
|
||||||
int8_t offset) { // offset from current
|
int8_t offset) { // offset from current
|
||||||
LINK *ptr;
|
Link *ptr;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
NO_LIST.error("ITERATOR::data_relative", ABORT);
|
NO_LIST.error("Iterator::data_relative", ABORT);
|
||||||
if (list->empty())
|
if (list->empty())
|
||||||
EMPTY_LIST.error("ITERATOR::data_relative", ABORT);
|
EMPTY_LIST.error("Iterator::data_relative", ABORT);
|
||||||
if (offset < -1)
|
if (offset < -1)
|
||||||
BAD_PARAMETER.error("ITERATOR::data_relative", ABORT, "offset < -l");
|
BAD_PARAMETER.error("Iterator::data_relative", ABORT, "offset < -l");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (offset == -1) {
|
if (offset == -1) {
|
||||||
@ -460,12 +458,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::forward
|
* Iterator::forward
|
||||||
*
|
*
|
||||||
* Move the iterator to the next element of the list.
|
* Move the iterator to the next element of the list.
|
||||||
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *forward() {
|
T *forward() {
|
||||||
if (list->empty()) {
|
if (list->empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -488,18 +486,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::extract
|
* Iterator::extract
|
||||||
*
|
*
|
||||||
* Do extraction by removing current from the list, deleting the cons cell
|
* Do extraction by removing current from the list, deleting the cons cell
|
||||||
* and returning the data to the caller, but NOT updating the iterator. (So
|
* and returning the data to the caller, but NOT updating the iterator. (So
|
||||||
* that any calling loop can do this.) The iterator's current points to
|
* that any calling loop can do this.) The iterator's current points to
|
||||||
* nullptr. If the data is to be deleted, this is the callers responsibility.
|
* nullptr. If the data is to be deleted, this is the callers responsibility.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *extract() {
|
T *extract() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!current) { // list empty or
|
if (!current) { // list empty or
|
||||||
// element extracted
|
// element extracted
|
||||||
NULL_CURRENT.error("ITERATOR::extract", ABORT);
|
NULL_CURRENT.error("Iterator::extract", ABORT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -525,12 +523,12 @@ public:
|
|||||||
} // remove from list
|
} // remove from list
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::move_to_first()
|
* Iterator::move_to_first()
|
||||||
*
|
*
|
||||||
* Move current so that it is set to the start of the list.
|
* Move current so that it is set to the start of the list.
|
||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *move_to_first() {
|
T *move_to_first() {
|
||||||
current = list->First();
|
current = list->First();
|
||||||
prev = list->last;
|
prev = list->last;
|
||||||
next = current != nullptr ? current->next : nullptr;
|
next = current != nullptr ? current->next : nullptr;
|
||||||
@ -538,13 +536,13 @@ public:
|
|||||||
} // go to start of list
|
} // go to start of list
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::move_to_last()
|
* Iterator::move_to_last()
|
||||||
*
|
*
|
||||||
* Move current so that it is set to the end of the list.
|
* Move current so that it is set to the end of the list.
|
||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
* (This function can't be INLINEd because it contains a loop)
|
* (This function can't be INLINEd because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *move_to_last() {
|
T *move_to_last() {
|
||||||
while (current != list->last) {
|
while (current != list->last) {
|
||||||
forward();
|
forward();
|
||||||
}
|
}
|
||||||
@ -557,7 +555,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::mark_cycle_pt()
|
* Iterator::mark_cycle_pt()
|
||||||
*
|
*
|
||||||
* Remember the current location so that we can tell whether we've returned
|
* Remember the current location so that we can tell whether we've returned
|
||||||
* to this point later.
|
* to this point later.
|
||||||
@ -569,7 +567,7 @@ public:
|
|||||||
void mark_cycle_pt() {
|
void mark_cycle_pt() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ITERATOR::mark_cycle_pt", ABORT);
|
NO_LIST.error("Iterator::mark_cycle_pt", ABORT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -590,7 +588,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::at_first()
|
* Iterator::at_first()
|
||||||
*
|
*
|
||||||
* Are we at the start of the list?
|
* Are we at the start of the list?
|
||||||
*
|
*
|
||||||
@ -603,7 +601,7 @@ public:
|
|||||||
} // Current is first?
|
} // Current is first?
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::at_last()
|
* Iterator::at_last()
|
||||||
*
|
*
|
||||||
* Are we at the end of the list?
|
* Are we at the end of the list?
|
||||||
*
|
*
|
||||||
@ -616,7 +614,7 @@ public:
|
|||||||
} // Current is last?
|
} // Current is last?
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::cycled_list()
|
* Iterator::cycled_list()
|
||||||
*
|
*
|
||||||
* Have we returned to the cycle_pt since it was set?
|
* Have we returned to the cycle_pt since it was set?
|
||||||
*
|
*
|
||||||
@ -626,7 +624,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::add_to_end
|
* Iterator::add_to_end
|
||||||
*
|
*
|
||||||
* Add a new element to the end of the list without moving the iterator.
|
* Add a new element to the end of the list without moving the iterator.
|
||||||
* This is provided because a single linked list cannot move to the last as
|
* This is provided because a single linked list cannot move to the last as
|
||||||
@ -635,13 +633,13 @@ public:
|
|||||||
queues.
|
queues.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_to_end( // element to add
|
void add_to_end( // element to add
|
||||||
CLASSNAME *new_data) {
|
T *new_data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ITERATOR::add_to_end", ABORT);
|
NO_LIST.error("Iterator::add_to_end", ABORT);
|
||||||
}
|
}
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
BAD_PARAMETER.error("ITERATOR::add_to_end", ABORT, "new_data is nullptr");
|
BAD_PARAMETER.error("Iterator::add_to_end", ABORT, "new_data is nullptr");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -652,7 +650,7 @@ public:
|
|||||||
this->add_before_stay_put(new_data);
|
this->add_before_stay_put(new_data);
|
||||||
list->last = prev;
|
list->last = prev;
|
||||||
} else { // Iteratr is elsewhere
|
} else { // Iteratr is elsewhere
|
||||||
auto new_element = new LINK;
|
auto new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
|
|
||||||
new_element->next = list->last->next;
|
new_element->next = list->last->next;
|
||||||
@ -663,7 +661,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::exchange()
|
* Iterator::exchange()
|
||||||
*
|
*
|
||||||
* Given another iterator, whose current element is a different element on
|
* Given another iterator, whose current element is a different element on
|
||||||
* the same list list OR an element of another list, exchange the two current
|
* the same list list OR an element of another list, exchange the two current
|
||||||
@ -672,7 +670,7 @@ public:
|
|||||||
* (This function hasn't been in-lined because its a bit big!)
|
* (This function hasn't been in-lined because its a bit big!)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void exchange( // positions of 2 links
|
void exchange( // positions of 2 links
|
||||||
ITERATOR *other_it) { // other iterator
|
Iterator *other_it) { // other iterator
|
||||||
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
||||||
|
|
||||||
/* Do nothing if either list is empty or if both iterators reference the same
|
/* Do nothing if either list is empty or if both iterators reference the same
|
||||||
@ -685,7 +683,7 @@ public:
|
|||||||
/* Error if either current element is deleted */
|
/* Error if either current element is deleted */
|
||||||
|
|
||||||
if (!current || !other_it->current) {
|
if (!current || !other_it->current) {
|
||||||
DONT_EXCHANGE_DELETED.error("ITERATOR.exchange", ABORT);
|
DONT_EXCHANGE_DELETED.error("Iterator.exchange", ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now handle the 4 cases: doubleton list; non-doubleton adjacent elements
|
/* Now handle the 4 cases: doubleton list; non-doubleton adjacent elements
|
||||||
@ -747,7 +745,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::length()
|
* Iterator::length()
|
||||||
*
|
*
|
||||||
* Return the length of the list
|
* Return the length of the list
|
||||||
*
|
*
|
||||||
@ -757,38 +755,39 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::sort()
|
* Iterator::sort()
|
||||||
*
|
*
|
||||||
* Sort the elements of the list, then reposition at the start.
|
* Sort the elements of the list, then reposition at the start.
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
list->sort(comparator);
|
list->sort(comparator);
|
||||||
move_to_first();
|
move_to_first();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
using ITERATOR = Iterator; // compat
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LINK *last = nullptr; // End of list
|
Link *last = nullptr; // End of list
|
||||||
|
|
||||||
//(Points to head)
|
//(Points to head)
|
||||||
LINK *First() { // return first
|
Link *First() { // return first
|
||||||
return last != nullptr ? last->next : nullptr;
|
return last != nullptr ? last->next : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LINK *First() const { // return first
|
const Link *First() const { // return first
|
||||||
return last != nullptr ? last->next : nullptr;
|
return last != nullptr ? last->next : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~CLIST() { // destructor
|
~ConsList() { // destructor
|
||||||
shallow_clear();
|
shallow_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLIST::internal_deep_clear
|
* ConsList::internal_deep_clear
|
||||||
*
|
*
|
||||||
* Used by the "deep_clear" member function of derived list
|
* Used by the "deep_clear" member function of derived list
|
||||||
* classes to destroy all the elements on the list.
|
* classes to destroy all the elements on the list.
|
||||||
@ -816,7 +815,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLIST::shallow_clear
|
* ConsList::shallow_clear
|
||||||
*
|
*
|
||||||
* Used by the destructor and the "shallow_clear" member function of derived
|
* Used by the destructor and the "shallow_clear" member function of derived
|
||||||
* list classes to destroy the list.
|
* list classes to destroy the list.
|
||||||
@ -845,12 +844,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void shallow_copy( // dangerous!!
|
void shallow_copy( // dangerous!!
|
||||||
CLIST *from_list) { // beware destructors!!
|
ConsList *from_list) { // beware destructors!!
|
||||||
last = from_list->last;
|
last = from_list->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLIST::assign_to_sublist
|
* ConsList::assign_to_sublist
|
||||||
*
|
*
|
||||||
* The list is set to a sublist of another list. "This" list must be empty
|
* The list is set to a sublist of another list. "This" list must be empty
|
||||||
* before this function is invoked. The two iterators passed must refer to
|
* before this function is invoked. The two iterators passed must refer to
|
||||||
@ -862,12 +861,12 @@ public:
|
|||||||
* end point is always the end_it position.
|
* end point is always the end_it position.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void assign_to_sublist( // to this list
|
void assign_to_sublist( // to this list
|
||||||
ITERATOR *start_it, // from list start
|
Iterator *start_it, // from list start
|
||||||
ITERATOR *end_it) { // from list end
|
Iterator *end_it) { // from list end
|
||||||
constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist");
|
constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist");
|
||||||
|
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
LIST_NOT_EMPTY.error("CLIST.assign_to_sublist", ABORT);
|
LIST_NOT_EMPTY.error("ConsList.assign_to_sublist", ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
last = start_it->extract_sublist(end_it);
|
last = start_it->extract_sublist(end_it);
|
||||||
@ -885,21 +884,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLIST::sort
|
* ConsList::sort
|
||||||
*
|
*
|
||||||
* Sort elements on list
|
* Sort elements on list
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
// Allocate an array of pointers, one per list element.
|
// Allocate an array of pointers, one per list element.
|
||||||
auto count = length();
|
auto count = length();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
// ptr array to sort
|
// ptr array to sort
|
||||||
std::vector<CLASSNAME *> base;
|
std::vector<T *> base;
|
||||||
base.reserve(count);
|
base.reserve(count);
|
||||||
|
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
|
|
||||||
// Extract all elements, putting the pointers in the array.
|
// Extract all elements, putting the pointers in the array.
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
@ -925,10 +924,10 @@ public:
|
|||||||
// Time is linear to add pre-sorted items to an empty list.
|
// Time is linear to add pre-sorted items to an empty list.
|
||||||
// If unique, then don't add duplicate entries.
|
// If unique, then don't add duplicate entries.
|
||||||
// Returns true if the element was added to the list.
|
// Returns true if the element was added to the list.
|
||||||
bool add_sorted(int comparator(const CLASSNAME *, const CLASSNAME *), bool unique, CLASSNAME *new_data) {
|
bool add_sorted(int comparator(const T *, const T *), bool unique, T *new_data) {
|
||||||
// Check for adding at the end.
|
// Check for adding at the end.
|
||||||
if (last == nullptr || comparator(last->data, new_data) < 0) {
|
if (last == nullptr || comparator(last->data, new_data) < 0) {
|
||||||
auto *new_element = new LINK;
|
auto *new_element = new Link;
|
||||||
new_element->data = new_data;
|
new_element->data = new_data;
|
||||||
if (last == nullptr) {
|
if (last == nullptr) {
|
||||||
new_element->next = new_element;
|
new_element->next = new_element;
|
||||||
@ -940,7 +939,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
} else if (!unique || last->data != new_data) {
|
} else if (!unique || last->data != new_data) {
|
||||||
// Need to use an iterator.
|
// Need to use an iterator.
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
auto data = it.data();
|
auto data = it.data();
|
||||||
if (data == new_data && unique) {
|
if (data == new_data && unique) {
|
||||||
@ -965,16 +964,16 @@ public:
|
|||||||
// the set difference minuend - subtrahend to this, being the elements
|
// the set difference minuend - subtrahend to this, being the elements
|
||||||
// of minuend that do not compare equal to anything in subtrahend.
|
// of minuend that do not compare equal to anything in subtrahend.
|
||||||
// If unique is true, any duplicates in minuend are also eliminated.
|
// If unique is true, any duplicates in minuend are also eliminated.
|
||||||
void set_subtract(int comparator(const CLASSNAME *, const CLASSNAME *), bool unique, CLIST *minuend,
|
void set_subtract(int comparator(const T *, const T *), bool unique, ConsList *minuend,
|
||||||
CLIST *subtrahend) {
|
ConsList *subtrahend) {
|
||||||
shallow_clear();
|
shallow_clear();
|
||||||
ITERATOR m_it(minuend);
|
Iterator m_it(minuend);
|
||||||
ITERATOR s_it(subtrahend);
|
Iterator s_it(subtrahend);
|
||||||
// Since both lists are sorted, finding the subtras that are not
|
// Since both lists are sorted, finding the subtras that are not
|
||||||
// minus is a case of a parallel iteration.
|
// minus is a case of a parallel iteration.
|
||||||
for (m_it.mark_cycle_pt(); !m_it.cycled_list(); m_it.forward()) {
|
for (m_it.mark_cycle_pt(); !m_it.cycled_list(); m_it.forward()) {
|
||||||
auto minu = m_it.data();
|
auto minu = m_it.data();
|
||||||
CLASSNAME *subtra = nullptr;
|
T *subtra = nullptr;
|
||||||
if (!s_it.empty()) {
|
if (!s_it.empty()) {
|
||||||
subtra = s_it.data();
|
subtra = s_it.data();
|
||||||
while (!s_it.at_last() && comparator(subtra, minu) < 0) {
|
while (!s_it.at_last() && comparator(subtra, minu) < 0) {
|
||||||
@ -989,11 +988,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLISTIZEH(CLASSNAME) \
|
#define CLISTIZEH(T) \
|
||||||
class CLASSNAME##_CLIST : public CLIST<CLASSNAME> { \
|
class T##_CLIST : public ConsList<T> { \
|
||||||
using CLIST<CLASSNAME>::CLIST; \
|
using ConsList<T>::ConsList; \
|
||||||
}; \
|
}; \
|
||||||
using CLASSNAME##_C_IT = CLIST<CLASSNAME>::ITERATOR;
|
using T##_C_IT = ConsList<T>::Iterator;
|
||||||
|
|
||||||
} // namespace tesseract
|
} // namespace tesseract
|
||||||
|
|
||||||
|
@ -72,10 +72,9 @@ lists.
|
|||||||
* Generic list class for singly linked lists with embedded links
|
* Generic list class for singly linked lists with embedded links
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
template <typename CLASSNAME>
|
template <typename T>
|
||||||
class ELIST {
|
class IntrusiveForwardList {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* CLASS - ELIST_LINK
|
* CLASS - ELIST_LINK
|
||||||
*
|
*
|
||||||
@ -83,33 +82,33 @@ public:
|
|||||||
*embedded links
|
*embedded links
|
||||||
*
|
*
|
||||||
* Note: No destructor - elements are assumed to be destroyed EITHER after
|
* Note: No destructor - elements are assumed to be destroyed EITHER after
|
||||||
* they have been extracted from a list OR by the ELIST destructor which
|
* they have been extracted from a list OR by the IntrusiveForwardList destructor which
|
||||||
* walks the list.
|
* walks the list.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
class LINK {
|
class Link {
|
||||||
friend class ITERATOR;
|
friend class Iterator;
|
||||||
friend class ELIST;
|
friend class IntrusiveForwardList;
|
||||||
|
|
||||||
CLASSNAME *next;
|
T *next;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LINK() {
|
Link() {
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
}
|
}
|
||||||
// constructor
|
// constructor
|
||||||
|
|
||||||
// The special copy constructor is used by lots of classes.
|
// The special copy constructor is used by lots of classes.
|
||||||
LINK(const LINK &) {
|
Link(const Link &) {
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The special assignment operator is used by lots of classes.
|
// The special assignment operator is used by lots of classes.
|
||||||
void operator=(const LINK &) {
|
void operator=(const Link &) {
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
using LINK = Link; // compat
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLASS - ELIST_ITERATOR
|
* CLASS - ELIST_ITERATOR
|
||||||
@ -118,36 +117,36 @@ public:
|
|||||||
*embedded links
|
*embedded links
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
class ITERATOR {
|
class Iterator {
|
||||||
friend void ELIST::assign_to_sublist(ITERATOR *, ITERATOR *);
|
friend void IntrusiveForwardList::assign_to_sublist(Iterator *, Iterator *);
|
||||||
|
|
||||||
ELIST *list; // List being iterated
|
IntrusiveForwardList *list; // List being iterated
|
||||||
CLASSNAME *prev; // prev element
|
T *prev; // prev element
|
||||||
CLASSNAME *current; // current element
|
T *current; // current element
|
||||||
CLASSNAME *next; // next element
|
T *next; // next element
|
||||||
CLASSNAME *cycle_pt; // point we are cycling the list to.
|
T *cycle_pt; // point we are cycling the list to.
|
||||||
bool ex_current_was_last; // current extracted was end of list
|
bool ex_current_was_last; // current extracted was end of list
|
||||||
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
||||||
bool started_cycling; // Have we moved off the start?
|
bool started_cycling; // Have we moved off the start?
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ITERATOR::extract_sublist()
|
* Iterator::extract_sublist()
|
||||||
*
|
*
|
||||||
* This is a private member, used only by ELIST::assign_to_sublist.
|
* This is a private member, used only by IntrusiveForwardList::assign_to_sublist.
|
||||||
* Given another iterator for the same list, extract the links from THIS to
|
* Given another iterator for the same list, extract the links from THIS to
|
||||||
* OTHER inclusive, link them into a new circular list, and return a
|
* OTHER inclusive, link them into a new circular list, and return a
|
||||||
* pointer to the last element.
|
* pointer to the last element.
|
||||||
* (Can't inline this function because it contains a loop)
|
* (Can't inline this function because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *extract_sublist( // from this current...
|
T *extract_sublist( // from this current...
|
||||||
ITERATOR *other_it) { // to other current
|
Iterator *other_it) { // to other current
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists");
|
constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists");
|
||||||
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
||||||
#endif
|
#endif
|
||||||
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
||||||
|
|
||||||
ITERATOR temp_it = *this;
|
Iterator temp_it = *this;
|
||||||
CLASSNAME *end_of_new_list;
|
T *end_of_new_list;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!other_it)
|
if (!other_it)
|
||||||
@ -170,7 +169,7 @@ public:
|
|||||||
temp_it.mark_cycle_pt();
|
temp_it.mark_cycle_pt();
|
||||||
do { // walk sublist
|
do { // walk sublist
|
||||||
if (temp_it.cycled_list()) { // can't find end pt
|
if (temp_it.cycled_list()) { // can't find end pt
|
||||||
BAD_SUBLIST.error("ITERATOR.extract_sublist", ABORT);
|
BAD_SUBLIST.error("Iterator.extract_sublist", ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp_it.at_last()) {
|
if (temp_it.at_last()) {
|
||||||
@ -208,7 +207,7 @@ public:
|
|||||||
} // to other current
|
} // to other current
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ITERATOR() { // constructor
|
Iterator() { // constructor
|
||||||
list = nullptr;
|
list = nullptr;
|
||||||
} // unassigned list
|
} // unassigned list
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -216,7 +215,7 @@ public:
|
|||||||
*
|
*
|
||||||
* CONSTRUCTOR - set iterator to specified list;
|
* CONSTRUCTOR - set iterator to specified list;
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
ITERATOR(ELIST *list_to_iterate) {
|
Iterator(IntrusiveForwardList *list_to_iterate) {
|
||||||
set_to_list(list_to_iterate);
|
set_to_list(list_to_iterate);
|
||||||
}
|
}
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -226,7 +225,7 @@ public:
|
|||||||
* over.
|
* over.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void set_to_list( // change list
|
void set_to_list( // change list
|
||||||
ELIST *list_to_iterate) {
|
IntrusiveForwardList *list_to_iterate) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list_to_iterate) {
|
if (!list_to_iterate) {
|
||||||
BAD_PARAMETER.error("ELIST_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr");
|
BAD_PARAMETER.error("ELIST_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr");
|
||||||
@ -249,7 +248,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_then_move( // add after current &
|
void add_after_then_move( // add after current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_after_then_move", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_after_then_move", ABORT);
|
||||||
@ -294,7 +293,7 @@ public:
|
|||||||
* the iterator to the new element.
|
* the iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_stay_put( // add after current &
|
void add_after_stay_put( // add after current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_after_stay_put", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_after_stay_put", ABORT);
|
||||||
@ -341,7 +340,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_then_move( // add before current &
|
void add_before_then_move( // add before current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_before_then_move", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_before_then_move", ABORT);
|
||||||
@ -382,7 +381,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_stay_put( // add before current &
|
void add_before_stay_put( // add before current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_before_stay_put", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_before_stay_put", ABORT);
|
||||||
@ -425,7 +424,7 @@ public:
|
|||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_after( // add a list &
|
void add_list_after( // add a list &
|
||||||
ELIST *list_to_add) {
|
IntrusiveForwardList *list_to_add) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_list_after", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_list_after", ABORT);
|
||||||
@ -471,7 +470,7 @@ public:
|
|||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_before( // add a list &
|
void add_list_before( // add a list &
|
||||||
ELIST *list_to_add) {
|
IntrusiveForwardList *list_to_add) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_list_before", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_list_before", ABORT);
|
||||||
@ -508,7 +507,7 @@ public:
|
|||||||
}
|
}
|
||||||
} // move to it 1st item
|
} // move to it 1st item
|
||||||
|
|
||||||
CLASSNAME *data() { // get current data
|
T *data() { // get current data
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::data", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::data", ABORT);
|
||||||
@ -526,9 +525,9 @@ public:
|
|||||||
* "offset" must not be less than -1.
|
* "offset" must not be less than -1.
|
||||||
* (This function can't be INLINEd because it contains a loop)
|
* (This function can't be INLINEd because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *data_relative( // get data + or - ...
|
T *data_relative( // get data + or - ...
|
||||||
int8_t offset) { // offset from current
|
int8_t offset) { // offset from current
|
||||||
CLASSNAME *ptr;
|
T *ptr;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -560,7 +559,7 @@ public:
|
|||||||
* Move the iterator to the next element of the list.
|
* Move the iterator to the next element of the list.
|
||||||
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *forward() {
|
T *forward() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
NO_LIST.error("ELIST_ITERATOR::forward", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::forward", ABORT);
|
||||||
@ -606,8 +605,8 @@ public:
|
|||||||
* this.) The iterator's current points to nullptr. If the extracted element
|
* this.) The iterator's current points to nullptr. If the extracted element
|
||||||
* is to be deleted, this is the callers responsibility.
|
* is to be deleted, this is the callers responsibility.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *extract() {
|
T *extract() {
|
||||||
CLASSNAME *extracted_link;
|
T *extracted_link;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
@ -643,7 +642,7 @@ public:
|
|||||||
* Move current so that it is set to the start of the list.
|
* Move current so that it is set to the start of the list.
|
||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *move_to_first() {
|
T *move_to_first() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::move_to_first", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::move_to_first", ABORT);
|
||||||
@ -662,7 +661,7 @@ public:
|
|||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
* (This function can't be INLINEd because it contains a loop)
|
* (This function can't be INLINEd because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *move_to_last() {
|
T *move_to_last() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
NO_LIST.error("ELIST_ITERATOR::move_to_last", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::move_to_last", ABORT);
|
||||||
@ -772,7 +771,7 @@ public:
|
|||||||
queues.
|
queues.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_to_end( // add at end &
|
void add_to_end( // add at end &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::add_to_end", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::add_to_end", ABORT);
|
||||||
@ -808,10 +807,10 @@ public:
|
|||||||
* (This function hasn't been in-lined because its a bit big!)
|
* (This function hasn't been in-lined because its a bit big!)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void exchange( // positions of 2 links
|
void exchange( // positions of 2 links
|
||||||
ITERATOR *other_it) { // other iterator
|
Iterator *other_it) { // other iterator
|
||||||
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
||||||
|
|
||||||
CLASSNAME *old_current;
|
T *old_current;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -905,7 +904,7 @@ public:
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST_ITERATOR::sort", ABORT);
|
NO_LIST.error("ELIST_ITERATOR::sort", ABORT);
|
||||||
@ -916,17 +915,17 @@ public:
|
|||||||
move_to_first();
|
move_to_first();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
using ITERATOR = Iterator; // compat
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CLASSNAME *last = nullptr; // End of list
|
T *last = nullptr; // End of list
|
||||||
//(Points to head)
|
//(Points to head)
|
||||||
CLASSNAME *First() { // return first
|
T *First() { // return first
|
||||||
return last ? last->next : nullptr;
|
return last ? last->next : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ELIST() {
|
~IntrusiveForwardList() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,16 +936,16 @@ public:
|
|||||||
|
|
||||||
/* Become a deep copy of src_list */
|
/* Become a deep copy of src_list */
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void deep_copy(const U *src_list, CLASSNAME *(*copier)(const CLASSNAME *)) {
|
void deep_copy(const U *src_list, T *(*copier)(const T *)) {
|
||||||
ITERATOR from_it(const_cast<U *>(src_list));
|
Iterator from_it(const_cast<U *>(src_list));
|
||||||
ITERATOR to_it(this);
|
Iterator to_it(this);
|
||||||
|
|
||||||
for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward())
|
for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward())
|
||||||
to_it.add_after_then_move((*copier)(from_it.data()));
|
to_it.add_after_then_move((*copier)(from_it.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST::internal_clear
|
* IntrusiveForwardList::internal_clear
|
||||||
*
|
*
|
||||||
* Used by the destructor and the "clear" member function of derived list
|
* Used by the destructor and the "clear" member function of derived list
|
||||||
* classes to destroy all the elements on the list.
|
* classes to destroy all the elements on the list.
|
||||||
@ -959,8 +958,8 @@ public:
|
|||||||
|
|
||||||
// destroy all links
|
// destroy all links
|
||||||
void internal_clear() {
|
void internal_clear() {
|
||||||
CLASSNAME *ptr;
|
T *ptr;
|
||||||
CLASSNAME *next;
|
T *next;
|
||||||
|
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
ptr = last->next; // set to first
|
ptr = last->next; // set to first
|
||||||
@ -983,12 +982,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void shallow_copy( // dangerous!!
|
void shallow_copy( // dangerous!!
|
||||||
ELIST *from_list) { // beware destructors!!
|
IntrusiveForwardList *from_list) { // beware destructors!!
|
||||||
last = from_list->last;
|
last = from_list->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST::assign_to_sublist
|
* IntrusiveForwardList::assign_to_sublist
|
||||||
*
|
*
|
||||||
* The list is set to a sublist of another list. "This" list must be empty
|
* The list is set to a sublist of another list. "This" list must be empty
|
||||||
* before this function is invoked. The two iterators passed must refer to
|
* before this function is invoked. The two iterators passed must refer to
|
||||||
@ -1000,12 +999,12 @@ public:
|
|||||||
* end point is always the end_it position.
|
* end point is always the end_it position.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void assign_to_sublist( // to this list
|
void assign_to_sublist( // to this list
|
||||||
ITERATOR *start_it, // from list start
|
Iterator *start_it, // from list start
|
||||||
ITERATOR *end_it) { // from list end
|
Iterator *end_it) { // from list end
|
||||||
constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist");
|
constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist");
|
||||||
|
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
LIST_NOT_EMPTY.error("ELIST.assign_to_sublist", ABORT);
|
LIST_NOT_EMPTY.error("IntrusiveForwardList.assign_to_sublist", ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
last = start_it->extract_sublist(end_it);
|
last = start_it->extract_sublist(end_it);
|
||||||
@ -1024,7 +1023,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST::sort
|
* IntrusiveForwardList::sort
|
||||||
*
|
*
|
||||||
* Sort elements on list
|
* Sort elements on list
|
||||||
* NB If you don't like the const declarations in the comparator, coerce yours:
|
* NB If you don't like the const declarations in the comparator, coerce yours:
|
||||||
@ -1032,16 +1031,16 @@ public:
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
// Allocate an array of pointers, one per list element.
|
// Allocate an array of pointers, one per list element.
|
||||||
auto count = length();
|
auto count = length();
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
// ptr array to sort
|
// ptr array to sort
|
||||||
std::vector<CLASSNAME *> base;
|
std::vector<T *> base;
|
||||||
base.reserve(count);
|
base.reserve(count);
|
||||||
|
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
|
|
||||||
// Extract all elements, putting the pointers in the array.
|
// Extract all elements, putting the pointers in the array.
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
@ -1070,8 +1069,8 @@ public:
|
|||||||
// list) - new_link is not added to the list and the function returns the
|
// list) - new_link is not added to the list and the function returns the
|
||||||
// pointer to the identical entry that already exists in the list
|
// pointer to the identical entry that already exists in the list
|
||||||
// (otherwise the function returns new_link).
|
// (otherwise the function returns new_link).
|
||||||
CLASSNAME *add_sorted_and_find(int comparator(const CLASSNAME *, const CLASSNAME *), bool unique,
|
T *add_sorted_and_find(int comparator(const T *, const T *), bool unique,
|
||||||
CLASSNAME *new_link) {
|
T *new_link) {
|
||||||
// Check for adding at the end.
|
// Check for adding at the end.
|
||||||
if (last == nullptr || comparator(last, new_link) < 0) {
|
if (last == nullptr || comparator(last, new_link) < 0) {
|
||||||
if (last == nullptr) {
|
if (last == nullptr) {
|
||||||
@ -1083,7 +1082,7 @@ public:
|
|||||||
last = new_link;
|
last = new_link;
|
||||||
} else {
|
} else {
|
||||||
// Need to use an iterator.
|
// Need to use an iterator.
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
auto *link = it.data();
|
auto *link = it.data();
|
||||||
int compare = comparator(link, new_link);
|
int compare = comparator(link, new_link);
|
||||||
@ -1104,22 +1103,24 @@ public:
|
|||||||
|
|
||||||
// Same as above, but returns true if the new entry was inserted, false
|
// Same as above, but returns true if the new entry was inserted, false
|
||||||
// if the identical entry already existed in the list.
|
// if the identical entry already existed in the list.
|
||||||
bool add_sorted(int comparator(const CLASSNAME *, const CLASSNAME *), bool unique, CLASSNAME *new_link) {
|
bool add_sorted(int comparator(const T *, const T *), bool unique, T *new_link) {
|
||||||
return (add_sorted_and_find(comparator, unique, new_link) == new_link);
|
return (add_sorted_and_find(comparator, unique, new_link) == new_link);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename CLASSNAME>
|
||||||
|
using ELIST = IntrusiveForwardList<CLASSNAME>;
|
||||||
|
|
||||||
// add TESS_API?
|
// add TESS_API?
|
||||||
// move templated lists to public include dirs?
|
// move templated lists to public include dirs?
|
||||||
#define ELISTIZEH(CLASSNAME) \
|
#define ELISTIZEH(T) \
|
||||||
class CLASSNAME##_LIST : public ELIST<CLASSNAME> { \
|
class T##_LIST : public IntrusiveForwardList<T> { \
|
||||||
public: \
|
public: \
|
||||||
using ELIST<CLASSNAME>::ELIST; \
|
using IntrusiveForwardList<T>::IntrusiveForwardList; \
|
||||||
}; \
|
}; \
|
||||||
class CLASSNAME##_IT : public ELIST<CLASSNAME>::ITERATOR { \
|
class T##_IT : public IntrusiveForwardList<T>::Iterator { \
|
||||||
public: \
|
public: \
|
||||||
using base = ELIST<CLASSNAME>::ITERATOR; \
|
using IntrusiveForwardList<T>::Iterator::Iterator; \
|
||||||
using base::base; \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tesseract
|
} // namespace tesseract
|
||||||
|
@ -51,11 +51,11 @@ i) The duplication in source does not affect the run time code size - the
|
|||||||
* Generic list class for doubly linked lists with embedded links
|
* Generic list class for doubly linked lists with embedded links
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
template <typename CLASSNAME>
|
template <typename T>
|
||||||
class ELIST2 {
|
class IntrusiveList {
|
||||||
public:
|
public:
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* CLASS - LINK
|
* CLASS - Link
|
||||||
*
|
*
|
||||||
* Generic link class for doubly linked lists with embedded links
|
* Generic link class for doubly linked lists with embedded links
|
||||||
*
|
*
|
||||||
@ -64,26 +64,26 @@ public:
|
|||||||
* walks the list.
|
* walks the list.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
class LINK {
|
class Link {
|
||||||
friend class ITERATOR;
|
friend class Iterator;
|
||||||
friend class ELIST2;
|
friend class IntrusiveList;
|
||||||
|
|
||||||
CLASSNAME *prev;
|
T *prev;
|
||||||
CLASSNAME *next;
|
T *next;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LINK() { // constructor
|
Link() { // constructor
|
||||||
prev = next = nullptr;
|
prev = next = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINK(const LINK &) = delete;
|
Link(const Link &) = delete;
|
||||||
|
|
||||||
// The assignment operator is required for WERD.
|
// The assignment operator is required for WERD.
|
||||||
void operator=(const LINK &) {
|
void operator=(const Link &) {
|
||||||
prev = next = nullptr;
|
prev = next = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
using LINK = Link; // compat
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLASS - ELIST2_ITERATOR
|
* CLASS - ELIST2_ITERATOR
|
||||||
@ -92,36 +92,36 @@ public:
|
|||||||
*links
|
*links
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
class ITERATOR {
|
class Iterator {
|
||||||
friend void ELIST2::assign_to_sublist(ITERATOR *, ITERATOR *);
|
friend void IntrusiveList::assign_to_sublist(Iterator *, Iterator *);
|
||||||
|
|
||||||
ELIST2 *list; // List being iterated
|
IntrusiveList *list; // List being iterated
|
||||||
CLASSNAME *prev; // prev element
|
T *prev; // prev element
|
||||||
CLASSNAME *current; // current element
|
T *current; // current element
|
||||||
CLASSNAME *next; // next element
|
T *next; // next element
|
||||||
CLASSNAME *cycle_pt; // point we are cycling the list to.
|
T *cycle_pt; // point we are cycling the list to.
|
||||||
bool ex_current_was_last; // current extracted was end of list
|
bool ex_current_was_last; // current extracted was end of list
|
||||||
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
bool ex_current_was_cycle_pt; // current extracted was cycle point
|
||||||
bool started_cycling; // Have we moved off the start?
|
bool started_cycling; // Have we moved off the start?
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST2_ITERATOR::extract_sublist()
|
* ELIST2_ITERATOR::extract_sublist()
|
||||||
*
|
*
|
||||||
* This is a private member, used only by ELIST2::assign_to_sublist.
|
* This is a private member, used only by IntrusiveList::assign_to_sublist.
|
||||||
* Given another iterator for the same list, extract the links from THIS to
|
* Given another iterator for the same list, extract the links from THIS to
|
||||||
* OTHER inclusive, link them into a new circular list, and return a
|
* OTHER inclusive, link them into a new circular list, and return a
|
||||||
* pointer to the last element.
|
* pointer to the last element.
|
||||||
* (Can't inline this function because it contains a loop)
|
* (Can't inline this function because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *extract_sublist( // from this current...
|
T *extract_sublist( // from this current...
|
||||||
ITERATOR *other_it) { // to other current
|
Iterator *other_it) { // to other current
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists");
|
constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists");
|
||||||
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points");
|
||||||
#endif
|
#endif
|
||||||
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list");
|
||||||
|
|
||||||
ITERATOR temp_it = *this;
|
Iterator temp_it = *this;
|
||||||
CLASSNAME *end_of_new_list;
|
T *end_of_new_list;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!other_it)
|
if (!other_it)
|
||||||
@ -193,8 +193,8 @@ public:
|
|||||||
*
|
*
|
||||||
* CONSTRUCTOR - set iterator to specified list;
|
* CONSTRUCTOR - set iterator to specified list;
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
ITERATOR( // constructor
|
Iterator( // constructor
|
||||||
ELIST2 *list_to_iterate) {
|
IntrusiveList *list_to_iterate) {
|
||||||
set_to_list(list_to_iterate);
|
set_to_list(list_to_iterate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ public:
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
void set_to_list( // change list
|
void set_to_list( // change list
|
||||||
ELIST2 *list_to_iterate) {
|
IntrusiveList *list_to_iterate) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list_to_iterate) {
|
if (!list_to_iterate) {
|
||||||
BAD_PARAMETER.error("ELIST2_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr");
|
BAD_PARAMETER.error("ELIST2_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr");
|
||||||
@ -229,7 +229,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_then_move( // add after current &
|
void add_after_then_move( // add after current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_after_then_move", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_after_then_move", ABORT);
|
||||||
@ -278,7 +278,7 @@ public:
|
|||||||
* the iterator to the new element.
|
* the iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_after_stay_put( // add after current &
|
void add_after_stay_put( // add after current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_after_stay_put", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_after_stay_put", ABORT);
|
||||||
@ -329,7 +329,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_then_move( // add before current &
|
void add_before_then_move( // add before current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_before_then_move", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_before_then_move", ABORT);
|
||||||
@ -375,7 +375,7 @@ public:
|
|||||||
* iterator to the new element.
|
* iterator to the new element.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_before_stay_put( // add before current &
|
void add_before_stay_put( // add before current &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_before_stay_put", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_before_stay_put", ABORT);
|
||||||
@ -423,7 +423,7 @@ public:
|
|||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_after( // add a list &
|
void add_list_after( // add a list &
|
||||||
ELIST2 *list_to_add) {
|
IntrusiveList *list_to_add) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_list_after", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_list_after", ABORT);
|
||||||
@ -473,7 +473,7 @@ public:
|
|||||||
* iterator.
|
* iterator.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_list_before( // add a list &
|
void add_list_before( // add a list &
|
||||||
ELIST2 *list_to_add) {
|
IntrusiveList *list_to_add) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_list_before", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_list_before", ABORT);
|
||||||
@ -514,7 +514,7 @@ public:
|
|||||||
}
|
}
|
||||||
} // move to it 1st item
|
} // move to it 1st item
|
||||||
|
|
||||||
CLASSNAME *data() { // get current data
|
T *data() { // get current data
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!current) {
|
if (!current) {
|
||||||
NULL_DATA.error("ELIST2_ITERATOR::data", ABORT);
|
NULL_DATA.error("ELIST2_ITERATOR::data", ABORT);
|
||||||
@ -531,9 +531,9 @@ public:
|
|||||||
* Return the data pointer to the element "offset" elements from current.
|
* Return the data pointer to the element "offset" elements from current.
|
||||||
* (This function can't be INLINEd because it contains a loop)
|
* (This function can't be INLINEd because it contains a loop)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *data_relative( // get data + or - ...
|
T *data_relative( // get data + or - ...
|
||||||
int8_t offset) { // offset from current
|
int8_t offset) { // offset from current
|
||||||
CLASSNAME *ptr;
|
T *ptr;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -565,7 +565,7 @@ public:
|
|||||||
* Move the iterator to the next element of the list.
|
* Move the iterator to the next element of the list.
|
||||||
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *forward() {
|
T *forward() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
NO_LIST.error("ELIST2_ITERATOR::forward", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::forward", ABORT);
|
||||||
@ -611,7 +611,7 @@ public:
|
|||||||
* Move the iterator to the previous element of the list.
|
* Move the iterator to the previous element of the list.
|
||||||
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
* REMEMBER: ALL LISTS ARE CIRCULAR.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *backward() {
|
T *backward() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
NO_LIST.error("ELIST2_ITERATOR::backward", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::backward", ABORT);
|
||||||
@ -655,8 +655,8 @@ public:
|
|||||||
* this.) The iterator's current points to nullptr. If the extracted element
|
* this.) The iterator's current points to nullptr. If the extracted element
|
||||||
* is to be deleted, this is the callers responsibility.
|
* is to be deleted, this is the callers responsibility.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *extract() {
|
T *extract() {
|
||||||
CLASSNAME *extracted_link;
|
T *extracted_link;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
@ -697,7 +697,7 @@ public:
|
|||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
// go to start of list
|
// go to start of list
|
||||||
CLASSNAME *move_to_first() {
|
T *move_to_first() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::move_to_first", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::move_to_first", ABORT);
|
||||||
@ -715,7 +715,7 @@ public:
|
|||||||
* Move current so that it is set to the end of the list.
|
* Move current so that it is set to the end of the list.
|
||||||
* Return data just in case anyone wants it.
|
* Return data just in case anyone wants it.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
CLASSNAME *move_to_last() {
|
T *move_to_last() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::move_to_last", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::move_to_last", ABORT);
|
||||||
@ -825,7 +825,7 @@ public:
|
|||||||
queues.
|
queues.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void add_to_end( // add at end &
|
void add_to_end( // add at end &
|
||||||
CLASSNAME *new_element) {
|
T *new_element) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::add_to_end", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::add_to_end", ABORT);
|
||||||
@ -863,10 +863,10 @@ public:
|
|||||||
* (This function hasn't been in-lined because its a bit big!)
|
* (This function hasn't been in-lined because its a bit big!)
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void exchange( // positions of 2 links
|
void exchange( // positions of 2 links
|
||||||
ITERATOR *other_it) { // other iterator
|
Iterator *other_it) { // other iterator
|
||||||
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists");
|
||||||
|
|
||||||
CLASSNAME *old_current;
|
T *old_current;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -972,7 +972,7 @@ public:
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!list) {
|
if (!list) {
|
||||||
NO_LIST.error("ELIST2_ITERATOR::sort", ABORT);
|
NO_LIST.error("ELIST2_ITERATOR::sort", ABORT);
|
||||||
@ -985,19 +985,19 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Don't use the following constructor.
|
// Don't use the following constructor.
|
||||||
ITERATOR() = delete;
|
Iterator() = delete;
|
||||||
};
|
};
|
||||||
|
using ITERATOR = Iterator; // compat
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CLASSNAME *last = nullptr; // End of list
|
T *last = nullptr; // End of list
|
||||||
//(Points to head)
|
//(Points to head)
|
||||||
CLASSNAME *First() { // return first
|
T *First() { // return first
|
||||||
return last ? last->next : nullptr;
|
return last ? last->next : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ELIST2() {
|
~IntrusiveList() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,16 +1008,16 @@ public:
|
|||||||
|
|
||||||
/* Become a deep copy of src_list */
|
/* Become a deep copy of src_list */
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void deep_copy(const U *src_list, CLASSNAME *(*copier)(const CLASSNAME *)) {
|
void deep_copy(const U *src_list, T *(*copier)(const T *)) {
|
||||||
ITERATOR from_it(const_cast<U *>(src_list));
|
Iterator from_it(const_cast<U *>(src_list));
|
||||||
ITERATOR to_it(this);
|
Iterator to_it(this);
|
||||||
|
|
||||||
for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward())
|
for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward())
|
||||||
to_it.add_after_then_move((*copier)(from_it.data()));
|
to_it.add_after_then_move((*copier)(from_it.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST2::internal_clear
|
* IntrusiveList::internal_clear
|
||||||
*
|
*
|
||||||
* Used by the destructor and the "clear" member function of derived list
|
* Used by the destructor and the "clear" member function of derived list
|
||||||
* classes to destroy all the elements on the list.
|
* classes to destroy all the elements on the list.
|
||||||
@ -1031,8 +1031,8 @@ public:
|
|||||||
// destroy all links
|
// destroy all links
|
||||||
void internal_clear() {
|
void internal_clear() {
|
||||||
// ptr to zapper functn
|
// ptr to zapper functn
|
||||||
CLASSNAME *ptr;
|
T *ptr;
|
||||||
CLASSNAME *next;
|
T *next;
|
||||||
|
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
ptr = last->next; // set to first
|
ptr = last->next; // set to first
|
||||||
@ -1055,12 +1055,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void shallow_copy( // dangerous!!
|
void shallow_copy( // dangerous!!
|
||||||
ELIST2 *from_list) { // beware destructors!!
|
IntrusiveList *from_list) { // beware destructors!!
|
||||||
last = from_list->last;
|
last = from_list->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST2::assign_to_sublist
|
* IntrusiveList::assign_to_sublist
|
||||||
*
|
*
|
||||||
* The list is set to a sublist of another list. "This" list must be empty
|
* The list is set to a sublist of another list. "This" list must be empty
|
||||||
* before this function is invoked. The two iterators passed must refer to
|
* before this function is invoked. The two iterators passed must refer to
|
||||||
@ -1072,8 +1072,8 @@ public:
|
|||||||
* end point is always the end_it position.
|
* end point is always the end_it position.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void assign_to_sublist( // to this list
|
void assign_to_sublist( // to this list
|
||||||
ITERATOR *start_it, // from list start
|
Iterator *start_it, // from list start
|
||||||
ITERATOR *end_it); // from list end
|
Iterator *end_it); // from list end
|
||||||
|
|
||||||
// # elements in list
|
// # elements in list
|
||||||
int32_t length() const {
|
int32_t length() const {
|
||||||
@ -1087,7 +1087,7 @@ public:
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ELIST2::sort
|
* IntrusiveList::sort
|
||||||
*
|
*
|
||||||
* Sort elements on list
|
* Sort elements on list
|
||||||
* NB If you don't like the const declarations in the comparator, coerce yours:
|
* NB If you don't like the const declarations in the comparator, coerce yours:
|
||||||
@ -1095,15 +1095,15 @@ public:
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
void sort( // sort elements
|
void sort( // sort elements
|
||||||
int comparator( // comparison routine
|
int comparator( // comparison routine
|
||||||
const CLASSNAME *, const CLASSNAME *)) {
|
const T *, const T *)) {
|
||||||
// Allocate an array of pointers, one per list element.
|
// Allocate an array of pointers, one per list element.
|
||||||
auto count = length();
|
auto count = length();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
// ptr array to sort
|
// ptr array to sort
|
||||||
std::vector<CLASSNAME *> base;
|
std::vector<T *> base;
|
||||||
base.reserve(count);
|
base.reserve(count);
|
||||||
|
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
|
|
||||||
// Extract all elements, putting the pointers in the array.
|
// Extract all elements, putting the pointers in the array.
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
@ -1127,7 +1127,7 @@ public:
|
|||||||
// Comparison function is the same as used by sort, i.e. uses double
|
// Comparison function is the same as used by sort, i.e. uses double
|
||||||
// indirection. Time is O(1) to add to beginning or end.
|
// indirection. Time is O(1) to add to beginning or end.
|
||||||
// Time is linear to add pre-sorted items to an empty list.
|
// Time is linear to add pre-sorted items to an empty list.
|
||||||
void add_sorted(int comparator(const CLASSNAME *, const CLASSNAME *), CLASSNAME *new_link) {
|
void add_sorted(int comparator(const T *, const T *), T *new_link) {
|
||||||
// Check for adding at the end.
|
// Check for adding at the end.
|
||||||
if (last == nullptr || comparator(last, new_link) < 0) {
|
if (last == nullptr || comparator(last, new_link) < 0) {
|
||||||
if (last == nullptr) {
|
if (last == nullptr) {
|
||||||
@ -1142,7 +1142,7 @@ public:
|
|||||||
last = new_link;
|
last = new_link;
|
||||||
} else {
|
} else {
|
||||||
// Need to use an iterator.
|
// Need to use an iterator.
|
||||||
ITERATOR it(this);
|
Iterator it(this);
|
||||||
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
|
||||||
auto link = it.data();
|
auto link = it.data();
|
||||||
if (comparator(link, new_link) > 0) {
|
if (comparator(link, new_link) > 0) {
|
||||||
@ -1158,16 +1158,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename CLASSNAME>
|
||||||
|
using ELIST2 = IntrusiveList<CLASSNAME>;
|
||||||
|
|
||||||
// add TESS_API?
|
// add TESS_API?
|
||||||
// move templated lists to public include dirs?
|
// move templated lists to public include dirs?
|
||||||
#define ELIST2IZEH(CLASSNAME) \
|
#define ELIST2IZEH(T) \
|
||||||
class CLASSNAME##_LIST : public ELIST2<CLASSNAME> { \
|
class T##_LIST : public IntrusiveList<T> { \
|
||||||
public: \
|
public: \
|
||||||
using ELIST2<CLASSNAME>::ELIST2; \
|
using IntrusiveList<T>::IntrusiveList; \
|
||||||
}; \
|
}; \
|
||||||
class CLASSNAME##_IT : public ELIST2<CLASSNAME>::ITERATOR { \
|
class T##_IT : public IntrusiveList<T>::Iterator { \
|
||||||
public: \
|
public: \
|
||||||
using base = ELIST2<CLASSNAME>::ITERATOR; \
|
using base = IntrusiveList<T>::Iterator; \
|
||||||
using base::base; \
|
using base::base; \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user