00001 /*
00002 This product contains certain software code or other information
00003 ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). The AT&T
00004 Software is provided to you "AS IS". YOU ASSUME TOTAL RESPONSIBILITY
00005 AND RISK FOR USE OF THE AT&T SOFTWARE. AT&T DOES NOT MAKE, AND
00006 EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
00007 WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00008 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
00009 TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
00010 WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
00011 PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
00012 WILL MEET YOUR REQUIREMENTS.
00013
00014 Unless you accept a license to use the AT&T Software, you shall not
00015 reverse compile, disassemble or otherwise reverse engineer this
00016 product to ascertain the source code for any AT&T Software.
00017
00018 (c) AT&T Corp. All rights reserved. AT&T is a registered trademark of AT&T Corp.
00019
00020 ***********************************************************************
00021
00022 History:
00023
00024 24/11/99 - initial release by Hartmut Liefke, liefke@seas.upenn.edu
00025 Dan Suciu, suciu@research.att.com
00026 */
00027
00028 //**************************************************************************
00029 //**************************************************************************
00030
00031 // This module contains class CurPath for storing the current path
00032 // within the XML document.
00033
00034 // The current path is stored as a sequence of labels -
00035 // They are kept stored in blocks of 32 labels in 'CurPathLabelBlock'
00036
00037 // The number of labels per block
00038 #define CURPATH_LABELBLOCKSIZE 32
00039
00040 struct CurPathLabelBlock
00041 {
00042 CurPathLabelBlock *prev,*next; // Previous and next label block
00043 TLabelID labels[CURPATH_LABELBLOCKSIZE];
00044 };
00045
00046 class CurPath;
00047
00048 class CurPathIterator
00049 // The iterator is used to iterate forward and backward within the
00050 // the current path
00051 {
00052 friend CurPath;
00053 CurPathLabelBlock *curblock; // The current block
00054 TLabelID *curlabel; // The current label (points into the current block)
00055
00056 public:
00057
00058 TLabelID GotoNext()
00059 // Go forward and return the next label
00060 // Returns LABEL_UNDEFINED, if the iterator is at the end of the path
00061 {
00062 if(curlabel==curblock->labels+CURPATH_LABELBLOCKSIZE)
00063 {
00064 curblock=curblock->next;
00065 if(curblock==NULL)
00066 return LABEL_UNDEFINED;
00067 curlabel=curblock->labels;
00068 }
00069 return *(curlabel++);
00070 }
00071
00072 TLabelID GotoPrev()
00073 // Go backward and return the next label
00074 // Returns LABEL_UNDEFINED, if the iterator is at the beginning of the path
00075 {
00076 curlabel--;
00077 if(curlabel==curblock->labels-1)
00078 {
00079 curblock=curblock->prev;
00080 if(curblock==NULL)
00081 return LABEL_UNDEFINED;
00082
00083 curlabel=curblock->labels+CURPATH_LABELBLOCKSIZE-1;
00084 }
00085 return *curlabel;
00086 }
00087 };
00088
00089 class CurPath
00090 // Implements the label stack
00091 {
00092 CurPathLabelBlock firstblock; // The first block
00093 CurPathLabelBlock *curblock; // The current (last) block
00094 TLabelID *curlabel; // The current label (within the current block)
00095 // The current label is always the *next free* pointer
00096
00097 #ifdef PROFILE
00098 unsigned curdepth,maxdepth;
00099 #endif
00100
00101 public:
00102 CurPath()
00103 {
00104 firstblock.prev=NULL;
00105 firstblock.next=NULL;
00106 curblock=&firstblock;
00107 curlabel=curblock->labels;
00108
00109 #ifdef PROFILE
00110 curdepth=maxdepth=0;
00111 #endif
00112 }
00113
00114 void AddLabel(TLabelID labelid)
00115 // Add a label at the end of the path
00116 {
00117 #ifdef PROFILE
00118 curdepth++;
00119 if(curdepth>maxdepth)
00120 maxdepth=curdepth;
00121 #endif
00122
00123 if(curlabel==curblock->labels+CURPATH_LABELBLOCKSIZE)
00124 // Is there not enough space in the current block?
00125 // ==> Create new block, if there is no next block
00126 // (We never delete blocks)
00127 {
00128 if(curblock->next==NULL)
00129 {
00130 curblock->next=new CurPathLabelBlock();
00131 curblock->next->prev=curblock;
00132 curblock->next->next=NULL;
00133 }
00134 curblock=curblock->next;
00135
00136 // We set the new current label
00137 curlabel=curblock->labels;
00138 }
00139 *curlabel=labelid;
00140 curlabel++;
00141 }
00142
00143 TLabelID RemoveLabel()
00144 // Removes the last label from the stack
00145 {
00146 #ifdef PROFILE
00147 curdepth--;
00148 #endif
00149
00150 curlabel--;
00151 if(curlabel==curblock->labels-1)
00152 // If the label in the previou block?
00153 // Go one block back
00154 {
00155 curblock=curblock->prev;
00156 if(curblock==NULL) // No previous block? => Exit
00157 return LABEL_UNDEFINED;
00158
00159 curlabel=curblock->labels+CURPATH_LABELBLOCKSIZE-1;
00160 }
00161 return *curlabel;
00162 }
00163
00164 void InitIterator(CurPathIterator *it)
00165 // Initializes an iterator for the path to the last label in the path
00166 {
00167 it->curblock=curblock;
00168 it->curlabel=curlabel;
00169 }
00170
00171 #ifdef PROFILE
00172 void PrintProfile()
00173 {
00174 printf("Maximal Depth=%lu\n",maxdepth);
00175 }
00176 #endif
00177 };
00178
00179 // There is one global path
00180 extern CurPath curpath;
1.2.11.1 written by Dimitri van Heesch,
© 1997-2001