00001 // +-------------------------------------------------------------------------+ 00002 // | I__n__t__e__L__i__b 0.6.10 development | 00003 // | Copyright (c) Andrey Vikt. Stolyarov <crocodil_AT_croco.net> 2000-2007. | 00004 // | | 00005 // | This is free software. The library part is available under | 00006 // | GNU LESSER GENERAL PUBLIC LICENSE v.2.1. | 00007 // | GNU LGPL v2.1 is found in docs/gnu_gpl2.txt, or at http://www.gnu.org | 00008 // | Please see also docs/readme.txt and visit http://www.intelib.org | 00009 // | | 00010 // | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! | 00011 // +-------------------------------------------------------------------------+ 00012 00013 00014 00015 00016 #include "sexpress.hpp" 00017 #if INTELIB_TEXT_REPRESENTATIONS == 1 00018 #include "sstring.hpp" 00019 #endif 00020 00021 #include "sbacklnk.hpp" 00022 00023 IntelibTypeId SExpressionBacklink:: 00024 TypeId(&SExpressionCons::TypeId, true); 00025 00026 SExpressionBacklink::~SExpressionBacklink() 00027 { 00028 if(Cdr().GetPtr() && !Cdr().IsEmptyList()) { 00029 SExpressionBacklink *nextitem = 00030 Cdr().DynamicCastGetPtr<SExpressionBacklink>(); 00031 if(nextitem && nextitem->back == this) 00032 nextitem->back = 0; 00033 } 00034 } 00035 00036 SExpression* SExpressionBacklink::Clone() const 00037 { 00038 throw IntelibX_not_implemented(); 00039 } 00040 00041 bool SExpressionBacklink::ConnectBack(const SBacklinkRef &where_to) 00042 { 00043 if(back || !where_to.Cdr().IsEmptyList()) return false; 00044 back = where_to.GetPtr(); 00045 back->Cdr() = this; 00046 return true; 00047 } 00048 00049 bool SExpressionBacklink::DisconnectBack() 00050 { 00051 if(!back) return false; 00052 back->Cdr() = *PTheEmptyList; 00053 back = 0; 00054 return true; 00055 } 00056 00057 void SExpressionBacklink::InsertAfter(const SReference &ref) 00058 { 00059 SExpressionBacklink *tmp = 00060 new SExpressionBacklink(ref, Cdr()); 00061 tmp->back = this; 00062 SExpressionBacklink *nextitem = 00063 Cdr().DynamicCastGetPtr<SExpressionBacklink>(); 00064 if(nextitem) nextitem->back = tmp; 00065 Cdr() = SReference(tmp); // this form takes care about *tmp 00066 } 00067 00068 bool SExpressionBacklink::RemoveNext() 00069 { 00070 if(Cdr().IsEmptyList()) return false; 00071 00072 SExpressionBacklink *item_to_remove = 00073 Cdr().DynamicCastGetPtr<SExpressionBacklink>(); 00074 00075 if(!item_to_remove) { 00076 // seems to be a dotted list 00077 Cdr() = *PTheEmptyList; 00078 } else { 00079 SExpressionBacklink *next_item = 00080 item_to_remove->Cdr().DynamicCastGetPtr<SExpressionBacklink>(); 00081 if(next_item) next_item->back = this; 00082 00083 SReference tmp = item_to_remove->Cdr(); 00084 item_to_remove->Cdr() = *PTheEmptyList; 00085 item_to_remove->back = 0; 00086 Cdr() = tmp; 00087 } 00088 return true; 00089 } 00090 00091 SBacklinkRef SExpressionBacklink::Prev() const 00092 { 00093 if(back) 00094 return SBacklinkRef(back); 00095 else 00096 return SBacklinkRef(*PTheEmptyList); 00097 } 00098 00099 SBacklinkRef SExpressionBacklink::Next() const 00100 { 00101 return Cdr(); 00102 } 00103 00104 00105 00106 SBacklinkRef::SBacklinkRef() 00107 : SReference(*PTheEmptyList) 00108 {} 00109 00110 SBacklinkRef::SBacklinkRef(SExpressionBacklink *ex) 00111 : SReference(ex) 00112 {} 00113 00114 SBacklinkRef:: 00115 SBacklinkRef(const SBacklinkRef &other) 00116 : SReference(other) 00117 {} 00118 00119 SBacklinkRef::SBacklinkRef(const SReference &other) 00120 : SReference(other) 00121 { 00122 if(other.IsEmptyList()) return; 00123 if(!other.GetPtr() || 00124 !other->TermType().IsSubtypeOf(SExpressionBacklink::TypeId) 00125 ) 00126 { 00127 throw IntelibX_not_a_backlink(other); 00128 } 00129 } 00130 00131 SBacklinkRef::~SBacklinkRef() 00132 {} 00133 00134 SBacklinkRef& SBacklinkRef::operator=(const SReference &ref) 00135 { 00136 if(!ref.IsEmptyList()) { 00137 if(!ref.GetPtr() || 00138 !ref->TermType().IsSubtypeOf(SExpressionBacklink::TypeId) 00139 ) 00140 { 00141 throw IntelibX_not_a_backlink(ref); 00142 } 00143 } 00144 this->SReference::operator=(ref); 00145 return *this; 00146 } 00147 00148 SExpressionBacklink* SBacklinkRef::GetPtr() const 00149 { 00150 if(IsEmptyList()) return 0; 00151 return static_cast<SExpressionBacklink*>(SReference::GetPtr()); 00152 } 00153 00154 void SBacklinkRef::InsertAfter(const SReference &r) 00155 { 00156 if(IsEmptyList()) { 00157 (*this) = new SExpressionBacklink(r, *PTheEmptyList); 00158 } else { 00159 (*this)->InsertAfter(r); 00160 } 00161 } 00162 00163 bool SBacklinkRef::Remove() 00164 { 00165 if(IsEmptyList()) return false; 00166 if(!(*this)->Prev().IsEmptyList()) { 00167 (*this) = (*this)->Prev(); 00168 (*this)->RemoveNext(); 00169 return true; 00170 } 00171 // no previous elem... 00172 SExpressionBacklink *nextitem = 00173 (*this)->Cdr().DynamicCastGetPtr<SExpressionBacklink>(); 00174 if(!nextitem) { 00175 // no next item as well, or it is a dotted end. just become empty. 00176 (*this) = *PTheEmptyList; 00177 return true; 00178 } 00179 // there's the next item... we'll advance forwards 00180 SBacklinkRef tmp = *this; 00181 (*this) = nextitem; 00182 nextitem->DisconnectBack(); 00183 return true; 00184 } 00185 00186 SBacklinkRef SBacklinkRef::operator,(const SReference &s) 00187 { 00188 if(IsEmptyList()) { 00189 SExpressionBacklink *tmp = 00190 new SExpressionBacklink(s, *PTheEmptyList); 00191 (*this) = tmp; 00192 return *this; 00193 } 00194 00195 SExpressionBacklink *sbl = GetPtr(); 00196 SExpressionBacklink *tmp; 00197 while((tmp = sbl->Cdr().DynamicCastGetPtr<SExpressionBacklink>())) 00198 { 00199 sbl = tmp; 00200 } 00201 sbl->InsertAfter(s); 00202 return SBacklinkRef(static_cast<SExpressionBacklink*> 00203 (sbl->Cdr().GetPtr())); 00204 } 00205 00206 SBacklinkRef SBacklinkRef::Begin() const 00207 { 00208 if(IsEmptyList()) return *this; 00209 SBacklinkRef res(*this); 00210 SBacklinkRef prev; 00211 while(!(prev = res->Prev()).IsEmptyList()) 00212 { 00213 res = prev; 00214 } 00215 return res; 00216 } 00217 00218 SBacklinkRef SBacklinkRef::End() const 00219 { 00220 if(IsEmptyList()) return *this; 00221 SBacklinkRef res(*this); 00222 SBacklinkRef next; 00223 while(!(next = res->Next()).IsEmptyList()) 00224 { 00225 res = next; 00226 } 00227 return res; 00228 } 00229 00230 SBacklinkRef& SBacklinkRef::operator++() 00231 { 00232 if(!IsEmptyList()) (*this) = GetPtr()->Cdr(); 00233 return *this; 00234 } 00235 00236 SBacklinkRef& SBacklinkRef::operator--() 00237 { 00238 if(!IsEmptyList()) (*this) = GetPtr()->Prev(); 00239 return *this; 00240 } 00241 00242 SBacklinkRef SBacklinkRef::operator++(int) 00243 { 00244 if(IsEmptyList()) return *this; 00245 SBacklinkRef res(*this); 00246 (*this) = GetPtr()->Cdr(); 00247 return res; 00248 } 00249 00250 SBacklinkRef SBacklinkRef::operator--(int) 00251 { 00252 if(IsEmptyList()) return *this; 00253 SBacklinkRef res(*this); 00254 (*this) = GetPtr()->Prev(); 00255 return res; 00256 } 00257 00258 00259 00260 IntelibX_not_a_backlink:: 00261 IntelibX_not_a_backlink(SReference a_param) 00262 : IntelibX("Not a backlinked cons", a_param) {} 00263