1/* 2 File: CArrayIterator.cpp 3 4 Contains: Implementation of the CArrayIterator class 5 6 7*/ 8 9#include "CDynamicArray.h" 10#include "CArrayIterator.h" 11 12//-------------------------------------------------------------------------------- 13#define super OSObject 14 OSDefineMetaClassAndStructors(CArrayIterator, OSObject); 15//-------------------------------------------------------------------------------- 16 17 18//-------------------------------------------------------------------------------- 19// CArrayIterator::SwitchArray 20//-------------------------------------------------------------------------------- 21void CArrayIterator::SwitchArray(CDynamicArray* newArray, Boolean itsForward) 22{ 23 // switch from one array to another 24 XASSERT(newArray); 25 26 if (fDynamicArray) 27 { 28 fDynamicArray->fIterator = RemoveFromList(); 29 fDynamicArray = nil; 30 } 31 32 init(newArray, 0, newArray->fSize - 1, itsForward); 33 34} // CArrayIterator::SwitchArray 35 36 37//-------------------------------------------------------------------------------- 38// CArrayIterator::AppendToList 39//-------------------------------------------------------------------------------- 40CArrayIterator* CArrayIterator::AppendToList(CArrayIterator* toList) 41{ 42 if (toList) 43 { 44 fNextLink = toList->fNextLink; 45 fPreviousLink = toList; 46 47 fNextLink->fPreviousLink = this; 48 toList->fNextLink = this; 49 } 50 return this; 51 52} // CArrayIterator::AppendToList 53 54 55//-------------------------------------------------------------------------------- 56// CArrayIterator::RemoveFromList 57//-------------------------------------------------------------------------------- 58CArrayIterator* CArrayIterator::RemoveFromList() 59{ 60 CArrayIterator * returnLink; 61 62 if (fNextLink == this) 63 returnLink = nil; 64 else 65 returnLink = fNextLink; 66 67 fNextLink->fPreviousLink = fPreviousLink; 68 fPreviousLink->fNextLink = fNextLink; 69 70 fNextLink = this; 71 fPreviousLink = this; 72 73 return returnLink; 74 75} // CArrayIterator::RemoveFromList 76 77 78//-------------------------------------------------------------------------------- 79// CArrayIterator::CArrayIterator(void) 80//-------------------------------------------------------------------------------- 81CArrayIterator * 82CArrayIterator::cArrayIterator() 83{ 84 CArrayIterator *obj = new CArrayIterator; 85 86 if (obj && !obj->init()) { 87 obj->release(); 88 obj = nil; 89 } 90 return obj; 91 92} // CArrayIterator::CArrayIterator 93 94//-------------------------------------------------------------------------------- 95// CArrayIterator::cArrayIterator(1) 96//-------------------------------------------------------------------------------- 97CArrayIterator * 98CArrayIterator::cArrayIterator(CDynamicArray* itsDynamicArray) 99{ 100 CArrayIterator *obj = new CArrayIterator; 101 102 XASSERT(itsDynamicArray); 103 // rely on Init to sanity check array bounds 104 105 if (obj && !obj->init(itsDynamicArray)) { 106 obj->release(); 107 obj = nil; 108 } 109 return obj; 110 111} // CArrayIterator::CArrayIterator 112 113//-------------------------------------------------------------------------------- 114// CArrayIterator::cArrayIterator(2) 115//-------------------------------------------------------------------------------- 116CArrayIterator * 117CArrayIterator::cArrayIterator(CDynamicArray* itsDynamicArray, Boolean itsForward) 118{ 119 CArrayIterator *obj = new CArrayIterator; 120 121 XASSERT(itsDynamicArray); 122 // rely on Init to sanity check array bounds 123 124 if (obj && !obj->init(itsDynamicArray, itsForward)) { 125 obj->release(); 126 obj = nil; 127 } 128 return obj; 129 130} // CArrayIterator::CArrayIterator 131 132 133 134//-------------------------------------------------------------------------------- 135// CArrayIterator::CArrayIterator(4) 136//-------------------------------------------------------------------------------- 137CArrayIterator * 138CArrayIterator::cArrayIterator(CDynamicArray* itsDynamicArray, ArrayIndex itsLowBound, 139 ArrayIndex itsHighBound, Boolean itsForward) 140{ 141 CArrayIterator *obj = new CArrayIterator; 142 143 XASSERT(itsDynamicArray); 144 // rely on Init to sanity check array bounds 145 146 if (obj && !obj->init(itsDynamicArray, itsLowBound, itsHighBound, itsForward)) { 147 obj->release(); 148 obj = nil; 149 } 150 return obj; 151 152} // CArrayIterator::CArrayIterator 153 154 155 156 157//-------------------------------------------------------------------------------- 158// CArrayIterator::free 159//-------------------------------------------------------------------------------- 160void 161CArrayIterator::free() 162{ 163 if (fDynamicArray) { 164 fDynamicArray->fIterator = RemoveFromList(); 165 fDynamicArray = nil; 166 } 167 168 super::free(); 169 170} // CArrayIterator::free 171 172 173//-------------------------------------------------------------------------------- 174// CArrayIterator::init(void) 175//-------------------------------------------------------------------------------- 176bool 177CArrayIterator::init() 178{ 179 if (!super::init()) return false; 180 181 fNextLink = this; 182 fPreviousLink = this; 183 fHighBound = kEmptyIndex; 184 fLowBound = kEmptyIndex; 185 fCurrentIndex = kEmptyIndex; 186 fIterateForward = kIterateForward; 187 fDynamicArray = nil; 188 189 return true; 190 191} // CArrayIterator::init 192 193//-------------------------------------------------------------------------------- 194// CArrayIterator::init(1) 195//-------------------------------------------------------------------------------- 196Boolean 197CArrayIterator::init(CDynamicArray* itsDynamicArray) 198{ 199 return init(itsDynamicArray, 0, itsDynamicArray->fSize - 1, kIterateForward); 200} 201 202//-------------------------------------------------------------------------------- 203// CArrayIterator::init(2) 204//-------------------------------------------------------------------------------- 205Boolean 206CArrayIterator::init(CDynamicArray* itsDynamicArray, Boolean itsForward) 207{ 208 return init(itsDynamicArray, 0, itsDynamicArray->fSize - 1, itsForward); 209} 210 211//-------------------------------------------------------------------------------- 212// CArrayIterator::init(4) 213//-------------------------------------------------------------------------------- 214Boolean 215CArrayIterator::init(CDynamicArray* itsDynamicArray, ArrayIndex itsLowBound, 216 ArrayIndex itsHighBound, Boolean itsForward) 217{ 218 219 if (!super::init()) return false; 220 221 require(itsDynamicArray, Fail); 222 223 fNextLink = this; 224 fPreviousLink = this; 225 fDynamicArray = itsDynamicArray; 226 227 // link me in to the list of iterations in progress 228 fDynamicArray->fIterator = AppendToList(fDynamicArray->fIterator); 229 230 // sanity check the bounds 231 InitBounds(itsLowBound, itsHighBound, itsForward); 232 233 return true; 234 235Fail: 236 return false; 237 238} // CArrayIterator::init 239 240 241//-------------------------------------------------------------------------------- 242// CArrayIterator::InitBounds 243//-------------------------------------------------------------------------------- 244void CArrayIterator::InitBounds(ArrayIndex itsLowBound, ArrayIndex itsHighBound, 245 Boolean itsForward) 246{ 247 fHighBound = (fDynamicArray->fSize > 0) ? MinMax(0, itsHighBound, fDynamicArray->fSize - 1) : kEmptyIndex; 248 fLowBound = (fHighBound > kEmptyIndex) ? MinMax(0, itsLowBound, fHighBound) : kEmptyIndex; 249 250 fIterateForward = itsForward; 251 252 Reset(); 253 254} // CArrayIterator::Init 255 256 257//-------------------------------------------------------------------------------- 258// CArrayIterator::ResetBounds 259//-------------------------------------------------------------------------------- 260void CArrayIterator::ResetBounds(Boolean goForward) 261{ 262 fHighBound = (fDynamicArray->fSize > 0) ? fDynamicArray->fSize - 1 : kEmptyIndex; 263 fLowBound = (fHighBound > kEmptyIndex) ? 0 : kEmptyIndex; 264 265 fIterateForward = goForward; 266 267 Reset(); 268 269} // CArrayIterator::Init 270 271 272//-------------------------------------------------------------------------------- 273// CArrayIterator::More 274//-------------------------------------------------------------------------------- 275Boolean CArrayIterator::More() 276{ 277 return (fDynamicArray != nil) ? (fCurrentIndex != kEmptyIndex) : false; 278 279} // CArrayIterator::More 280 281 282//-------------------------------------------------------------------------------- 283// CArrayIterator::Reset 284//-------------------------------------------------------------------------------- 285void CArrayIterator::Reset() 286{ 287 fCurrentIndex = (fIterateForward) ? fLowBound : fHighBound; 288 289} // CArrayIterator::Reset 290 291 292//-------------------------------------------------------------------------------- 293// CArrayIterator::DeleteArray 294//-------------------------------------------------------------------------------- 295void CArrayIterator::DeleteArray() 296{ 297 // inform everyone else in the list that the array is gone 298 if (fNextLink != fDynamicArray->fIterator) 299 fNextLink->DeleteArray(); 300 301 // we no longer have an array 302 fDynamicArray = nil; 303 304} // CArrayIterator::~CArrayIterator 305 306 307//-------------------------------------------------------------------------------- 308// CArrayIterator::Advance 309//-------------------------------------------------------------------------------- 310void CArrayIterator::Advance() 311{ 312 if (fIterateForward) 313 { 314 if (fCurrentIndex < fHighBound) 315 ++fCurrentIndex; 316 else 317 fCurrentIndex = kEmptyIndex; 318 } 319 else 320 { 321 if (fCurrentIndex > fLowBound) 322 --fCurrentIndex; 323 else 324 fCurrentIndex = kEmptyIndex; 325 } 326 327} // CArrayIterator::Advance 328 329 330//-------------------------------------------------------------------------------- 331// CArrayIterator::RemoveElementsAt 332//-------------------------------------------------------------------------------- 333void CArrayIterator::RemoveElementsAt(ArrayIndex theIndex, ArrayIndex theCount) 334{ 335 // tuck the endpoints of the iteration in to match 336 if (theIndex < fLowBound) 337 fLowBound -= theCount; 338 339 if (theIndex <= fHighBound) 340 fHighBound -= theCount; 341 342 if (fIterateForward) 343 { 344 // If the removed element was !in the range yet to be iterated 345 // then bend the fCurrentIndex to account for it. 346 if (theIndex <= fCurrentIndex) 347 fCurrentIndex -= theCount; 348 } 349 else 350 { 351 // Iterating backwards 352 // If the removed element was IN the range yet to be iterated 353 // then bend the fCurrentIndex to account for it. 354 if (theIndex < fCurrentIndex) 355 fCurrentIndex -= theCount; 356 } 357 358 // hand off control to the next link until you hit the last 359 // link in the circular chain 360 if (fDynamicArray && fNextLink != fDynamicArray->fIterator) 361 fNextLink->RemoveElementsAt(theIndex, theCount); 362 363} // CArrayIterator::RemoveElementsAt 364 365 366//-------------------------------------------------------------------------------- 367// CArrayIterator::InsertElementsBefore 368//-------------------------------------------------------------------------------- 369void CArrayIterator::InsertElementsBefore(ArrayIndex theIndex, ArrayIndex theCount) 370{ 371 // bump the endpoints of this iteration out to match 372 if (theIndex <= fLowBound) 373 fLowBound += theCount; 374 375 if (theIndex <= fHighBound) 376 fHighBound += theCount; 377 378 if (fIterateForward) 379 { 380 // If the inserted element was !in the range yet to be 381 // iterated then bend the fCurrentIndex to account for it. 382 if (theIndex <= fCurrentIndex) 383 fCurrentIndex += theCount; 384 } 385 else 386 { 387 // Iterating backward 388 // If the inserted element was IN the range yet to be 389 // iterated then bend the fCurrentIndex to account for it. 390 if (theIndex < fCurrentIndex) 391 fCurrentIndex += theCount; 392 } 393 394 // hand off control to the next link until you hit the last 395 // link in the circular chain 396 if (fDynamicArray && fNextLink != fDynamicArray->fIterator) 397 fNextLink->InsertElementsBefore(theIndex, theCount); 398 399} // CArrayIterator::InsertElementsBefore 400 401 402//-------------------------------------------------------------------------------- 403// CArrayIterator::CurrentIndex 404//-------------------------------------------------------------------------------- 405ArrayIndex CArrayIterator::CurrentIndex() 406{ 407 return (fDynamicArray != nil) ? fCurrentIndex : kEmptyIndex; 408 409} // CArrayIterator::CurrentIndex 410 411 412//-------------------------------------------------------------------------------- 413// CArrayIterator::FirstIndex 414//-------------------------------------------------------------------------------- 415ArrayIndex CArrayIterator::FirstIndex() 416{ 417 Reset(); 418 419 return More() ? fCurrentIndex : kEmptyIndex; 420 421} // CArrayIterator::FirstIndex 422 423 424//-------------------------------------------------------------------------------- 425// CArrayIterator::NextIndex 426//-------------------------------------------------------------------------------- 427ArrayIndex CArrayIterator::NextIndex() 428{ 429 Advance(); 430 431 return More() ? fCurrentIndex : kEmptyIndex; 432 433} // CArrayIterator::NextIndex 434 435 436