📄 elst.cpp
字号:
/********************************************************************** * File: elst.c (Formerly elist.c) * Description: Embedded list handling code which is not in the include file. * Author: Phil Cheatle * Created: Fri Jan 04 13:55:49 GMT 1991 * * (C) Copyright 1991, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/#include "mfcpch.h" //precompiled headers#include <stdlib.h>#include "elst.h"/*********************************************************************** * MEMBER FUNCTIONS OF CLASS: ELIST_LINK * ===================================== **********************************************************************//*********************************************************************** * ELIST_LINK::serialise_asc * * Generates an error as it should never be called. **********************************************************************/void ELIST_LINK::serialise_asc( //default serialise FILE *f) { SERIALISE_LINKS.error ("ELIST_LINK::serialise_asc", ABORT, "Don't call this, override!");}void ELIST_LINK::de_serialise_asc( //default de_serialise FILE *f) { SERIALISE_LINKS.error ("ELIST_LINK::de_serialise_asc", ABORT, "Don't call this, override!");}/*********************************************************************** * MEMBER FUNCTIONS OF CLASS: ELIST * ================================ **********************************************************************//*********************************************************************** * ELIST::internal_clear * * Used by the destructor and the "clear" member function of derived list * classes to destroy all the elements on the list. * The calling function passes a "zapper" function which can be called to * delete each element of the list, regardless of its derived type. This * technique permits a generic clear function to destroy elements of * different derived types correctly, without requiring virtual functions and * the consequential memory overhead. **********************************************************************/voidELIST::internal_clear ( //destroy all linksvoid (*zapper) (ELIST_LINK *)) { //ptr to zapper functn ELIST_LINK *ptr; ELIST_LINK *next; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::internal_clear", ABORT, NULL); #endif if (!empty ()) { ptr = last->next; //set to first last->next = NULL; //break circle last = NULL; //set list empty while (ptr) { next = ptr->next; zapper(ptr); ptr = next; } }}/*********************************************************************** * ELIST::internal_deep_copy * * Used during explict deep copy of a list. The "copier" function passed * allows each element to be correctly deep copied (assuming that each class * in the inheritance hierarchy does properly deep copies its members). The * function passing technique is as for "internal_clear". **********************************************************************/void //ptr to copier functnELIST::internal_deep_copy (ELIST_LINK * (*copier) (ELIST_LINK *),const ELIST * list) { //list being copied ELIST_ITERATOR from_it ((ELIST *) list); ELIST_ITERATOR to_it(this); #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::internal_deep_copy", ABORT, NULL); if (!list) BAD_PARAMETER.error ("ELIST::internal_deep_copy", ABORT, "source list is NULL"); #endif for (from_it.mark_cycle_pt (); !from_it.cycled_list (); from_it.forward ()) to_it.add_after_then_move (copier (from_it.data ()));}/*********************************************************************** * ELIST::assign_to_sublist * * 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 * the same list, different from "this" one. The sublist removed is the * inclusive list from start_it's current position to end_it's current * position. If this range passes over the end of the source list then the * source list has its end set to the previous element of start_it. The * extracted sublist is unaffected by the end point of the source list, its * end point is always the end_it position. **********************************************************************/void ELIST::assign_to_sublist( //to this list ELIST_ITERATOR *start_it, //from list start ELIST_ITERATOR *end_it) { //from list end const ERRCODE LIST_NOT_EMPTY = "Destination list must be empty before extracting a sublist"; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::assign_to_sublist", ABORT, NULL); #endif if (!empty ()) LIST_NOT_EMPTY.error ("ELIST.assign_to_sublist", ABORT, NULL); last = start_it->extract_sublist (end_it);}/*********************************************************************** * ELIST::length * * Return count of elements on list **********************************************************************/INT32 ELIST::length() { //count elements ELIST_ITERATOR it(this); INT32 count = 0; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::length", ABORT, NULL); #endif for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) count++; return count;}/*********************************************************************** * ELIST::sort * * Sort elements on list * NB If you dont like the const declarations in the comparator, coerce yours: * ( int (*)(const void *, const void *) **********************************************************************/voidELIST::sort ( //sort elementsint comparator ( //comparison routineconst void *, const void *)) { ELIST_ITERATOR it(this); INT32 count; ELIST_LINK **base; //ptr array to sort ELIST_LINK **current; INT32 i; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::sort", ABORT, NULL); #endif /* Allocate an array of pointers, one per list element */ count = length (); base = (ELIST_LINK **) malloc (count * sizeof (ELIST_LINK *)); /* Extract all elements, putting the pointers in the array */ current = base; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { *current = it.extract (); current++; } /* Sort the pointer array */ qsort ((char *) base, count, sizeof (*base), comparator); /* Rebuild the list from the sorted pointers */ current = base; for (i = 0; i < count; i++) { it.add_to_end (*current); current++; } free(base);}/*********************************************************************** * ELIST::prep_serialise * * Replace the last member with a count of elements for serialisation. * This is used on list objects which are members of objects being * serialised. The containing object has been shallow copied and this member * function is invoked on the COPY. **********************************************************************/void ELIST::prep_serialise() { ELIST_ITERATOR this_it(this); INT32 count = 0; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::prep_serialise", ABORT, NULL); #endif count = 0; if (!empty ()) for (this_it.mark_cycle_pt (); !this_it.cycled_list (); this_it.forward ()) count++; last = (ELIST_LINK *) count;}/*********************************************************************** * ELIST::internal_dump * * Cause each element on the list to be serialised by walking the list and * calling the element_serialiser function for each element. The * element_serialiser simply does the appropriate coercion of the element to * its real type and then invokes the elements serialise function **********************************************************************/voidELIST::internal_dump (FILE * f,void element_serialiser (FILE *, ELIST_LINK *)) { ELIST_ITERATOR this_it(this); #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::internal_dump", ABORT, NULL); #endif if (!empty ()) for (this_it.mark_cycle_pt (); !this_it.cycled_list (); this_it.forward ()) element_serialiser (f, this_it.data ());}/*********************************************************************** * ELIST::internal_de_dump * * Cause each element on the list to be de_serialised by extracting the count * of elements on the list, (held in the last member of the dumped version of * the list object), and then de-serialising that number of list elements, * adding each to the end of the reconstructed list. **********************************************************************/voidELIST::internal_de_dump (FILE * f,ELIST_LINK * element_de_serialiser (FILE *)) { INT32 count = (ptrdiff_t) last; ELIST_ITERATOR this_it; ELIST_LINK *de_serialised_element; #ifdef _DEBUG if (!this) NULL_OBJECT.error ("ELIST::internal_de_dump", ABORT, NULL); #endif last = NULL; this_it.set_to_list (this); for (; count > 0; count--) { de_serialised_element = element_de_serialiser (f); //ignore old ptr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -