• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

okteta

  • sources
  • kde-4.12
  • kdesdk
  • okteta
  • core
  • piecetable
piecetable.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the Okteta Core library, made within the KDE community.
3 
4  Copyright 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) version 3, or any
10  later version accepted by the membership of KDE e.V. (or its
11  successor approved by the membership of KDE e.V.), which shall
12  act as a proxy defined in Section 6 of version 3 of the license.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include "piecetable.h"
24 
25 // Qt
26 #include <QtCore/QMutableLinkedListIterator>
27 
28 
29 namespace KPieceTable
30 {
31 
32 PieceTable::PieceTable( Size size )
33 {
34  init( size );
35 }
36 
37 void PieceTable::init( Size size )
38 {
39  mList.clear();
40  if( size > 0 )
41  mList.append( Piece(0,size,Piece::OriginalStorage) );
42 
43  mSize = size;
44 }
45 
46 
47 bool PieceTable::getStorageData( int* storageId, Address* storageOffset, Address dataOffset ) const
48 {
49  bool result = false;
50 
51  // TODO: use width or offset from current and next?
52  AddressRange dataRange( 0, -1 );
53  foreach( const Piece& piece, mList )
54  {
55  dataRange.setEndByWidth( piece.width() );
56 
57  if( dataRange.includes(dataOffset) )
58  {
59  *storageId = piece.storageId();
60 // kDebug() <<piece.start()<<"+"<<dataRange.localIndex( dataOffset );
61  *storageOffset = piece.start() + dataRange.localIndex( dataOffset );
62  result = true;
63  break;
64  }
65  dataRange.setStart( dataRange.nextBehindEnd() );
66  }
67 
68  return result;
69 }
70 
71 // TODO: optimize search from behind if dataOffset is large (perhaps by counting total size
72 // TODO: combine sucsequenting inserts, also on other changes if possible link neighbors
73 void PieceTable::insert( Address insertDataOffset, Size insertLength, Address storageOffset )
74 {
75  const int storageId = Piece::ChangeStorage;
76  QMutableLinkedListIterator<Piece> it( mList );
77 
78  const Piece insertPiece( storageOffset, insertLength, storageId );
79 
80  // TODO: use width or offset from current and next?
81  AddressRange dataRange( 0, -1 );
82  while( it.hasNext() )
83  {
84  Piece& piece = it.peekNext();
85  dataRange.setEndByWidth( piece.width() );
86 
87  // piece starts at offset?
88  if( dataRange.start() == insertDataOffset )
89  {
90  it.insert( insertPiece );
91  break;
92  }
93  if( dataRange.nextBehindEnd() == insertDataOffset )
94  {
95  if( piece.append(insertPiece) )
96  break;
97  }
98  it.next();
99  if( dataRange.includes(insertDataOffset) )
100  {
101  const Piece secondPiece = piece.splitAtLocal( dataRange.localIndex(insertDataOffset) );
102  it.insert( insertPiece );
103  it.insert( secondPiece );
104  break;
105  }
106 
107  dataRange.setStart( dataRange.nextBehindEnd() );
108  }
109  if( !it.hasNext() && (dataRange.start() == insertDataOffset) )
110  it.insert( insertPiece );
111 
112  mSize += insertLength;
113 }
114 
115 void PieceTable::insert( Address insertDataOffset, const PieceList& insertPieceList )
116 {
117  if( insertPieceList.isEmpty() )
118  return;
119 
120  bool isInserted = false;
121  QMutableLinkedListIterator<Piece> it( mList );
122 
123  // TODO: use width or offset from current and next?
124  AddressRange dataRange( 0, -1 );
125  while( it.hasNext() )
126  {
127  Piece& piece = it.peekNext();
128  dataRange.setEndByWidth( piece.width() );
129 
130  // piece starts at offset?
131  if( dataRange.start() == insertDataOffset )
132  {
133  int i = 0;
134  if( it.hasPrevious() )
135  {
136  Piece& previousPiece = it.peekPrevious();
137  if( previousPiece.append(insertPieceList.at(0)) )
138  {
139  if( insertPieceList.size() == 1 )
140  {
141  if( previousPiece.append(piece) )
142  {
143  it.next();
144  it.remove();
145  }
146  isInserted = true;
147  break;
148  }
149  ++i;
150  }
151  }
152 
153  const int lastIndex = insertPieceList.size()-1;
154  for( ; i<lastIndex; ++i )
155  it.insert( insertPieceList.at(i) );
156  const Piece& lastInsertPiece = insertPieceList.at( lastIndex );
157  if( ! piece.prepend(lastInsertPiece) )
158  it.insert( lastInsertPiece );
159  isInserted = true;
160  break;
161  }
162  it.next();
163  if( dataRange.includes(insertDataOffset) )
164  {
165  const Piece secondPiece = piece.splitAtLocal( dataRange.localIndex(insertDataOffset) );
166  for( int i=0; i<insertPieceList.size(); ++i )
167  it.insert( insertPieceList.at(i) );
168  it.insert( secondPiece );
169  isInserted = true;
170  break;
171  }
172 
173  dataRange.setStart( dataRange.nextBehindEnd() );
174  }
175  if( ! isInserted && (dataRange.start() == insertDataOffset) )
176  {
177  int i = 0;
178  if( it.hasPrevious() )
179  {
180  Piece& previousPiece = it.peekPrevious();
181  if( previousPiece.append(insertPieceList.at(0)) )
182  ++i;
183  }
184  for( ; i<insertPieceList.size(); ++i )
185  it.insert( insertPieceList.at(i) );
186  }
187 
188  mSize += insertPieceList.totalLength();
189 }
190 
191 // TODO: make algorithm simpler
192 PieceList PieceTable::remove( const AddressRange& removeRange )
193 {
194  PieceList removedPieceList;
195 
196  AddressRange dataRange( 0, -1 );
197 
198  QLinkedList<Piece>::Iterator it = mList.begin();
199  while( it != mList.end() )
200  {
201  Piece* piece = &*it;
202  dataRange.setEndByWidth( piece->width() );
203 
204  if( dataRange.includes(removeRange.start()) )
205  {
206  QLinkedList<Piece>::Iterator firstRemoved = it;
207  const Address firstDataRangeStart = dataRange.start();
208 // int sections = 1;
209 
210  if( dataRange.includesInside(removeRange) )
211  {
212  const AddressRange localRange = dataRange.localRange( removeRange );
213  const Piece removedPiece = piece->subPiece( localRange );
214  const Piece secondPiece = piece->removeLocal( localRange );
215 
216  mList.insert( ++it, secondPiece );
217  removedPieceList.append( removedPiece );
218 // kDebug() << "removed intern";
219  break;
220  }
221  do
222  {
223  if( dataRange.includes(removeRange.end()) )
224  {
225  QLinkedList<Piece>::Iterator lastRemoved = it;
226 // kDebug() << removeRange.start() << removeRange.end() << firstDataRangeStart << dataRange.end();
227  // cut from first section if not all
228  bool onlyCompletePiecesRemoved = true;
229  if( firstDataRangeStart < removeRange.start() )
230  {
231  const Address newLocalEnd = removeRange.start() - firstDataRangeStart - 1;
232  const Piece removedPiece = (*firstRemoved).removeEndBehindLocal( newLocalEnd );
233  removedPieceList.append( removedPiece );
234 
235  ++firstRemoved;
236  onlyCompletePiecesRemoved = false;
237 // kDebug() << "end of first removed"<<piece->start()<<piece->end()<<"->"<<removedPiece.start()<<removedPiece.end();
238 // --sections;
239  }
240 
241  Piece removedPartialPieceFromLast;
242  // cut from last section if not all
243  if( removeRange.end() < dataRange.end() )
244  {
245  const Address newLocalStart = dataRange.localIndex( removeRange.end() ) + 1;
246  removedPartialPieceFromLast = piece->removeStartBeforeLocal( newLocalStart );
247 
248  onlyCompletePiecesRemoved = false;
249 // kDebug() << "start of last removed"<<piece->start()<<piece->end()<<"->"<<removedPartialPieceFromLast.start()<<removedPartialPieceFromLast.end();
250 // --sections;
251  }
252  else
253  {
254  ++lastRemoved;
255  }
256 
257  for( QLinkedList<Piece>::Iterator it = firstRemoved; it!=lastRemoved; ++it )
258  removedPieceList.append( *it );
259  if( removedPartialPieceFromLast.isValid() )
260  removedPieceList.append( removedPartialPieceFromLast );
261 
262  if( onlyCompletePiecesRemoved )
263  {
264  if( firstRemoved != mList.begin() && lastRemoved != mList.end() )
265  {
266  QLinkedList<Piece>::Iterator beforeFirstRemoved = firstRemoved - 1;
267  if( (*beforeFirstRemoved).append(*lastRemoved) )
268  ++lastRemoved;
269  }
270  }
271 
272  mList.erase( firstRemoved, lastRemoved );
273 // kDebug() << "removed "<<sections;
274  break;
275  }
276  dataRange.setStart( dataRange.nextBehindEnd() );
277  ++it;
278 // ++sections;
279  // removeRange is longer than content TODO: just quit or at least remove till the end?
280  if( it == mList.end() )
281  break;
282  piece = &*it;
283  dataRange.setEndByWidth( piece->width() );
284  }
285  while( it != mList.end() );
286  break;
287  }
288 
289  dataRange.setStart( dataRange.nextBehindEnd() );
290  ++it;
291  }
292 
293  mSize -= removeRange.width();
294 
295 // kDebug()<<"end:"<<asStringList(mList);
296  return removedPieceList;
297 }
298 
299 PieceList PieceTable::replace( const AddressRange& removeRange, Size insertLength, Address storageOffset )
300 {
301  PieceList removedPieceList = remove( removeRange );
302  insert( removeRange.start(), insertLength, storageOffset );
303  return removedPieceList;
304 }
305 void PieceTable::replace( const AddressRange& removeRange, const PieceList& insertPieceList )
306 {
307  remove( removeRange );
308  insert( removeRange.start(), insertPieceList );
309 }
310 
311 void PieceTable::swap( Address firstStart, const AddressRange& secondRange )
312 {
313  AddressRange dataRange( 0, -1 );
314 
315  QLinkedList<Piece>::Iterator it = mList.begin();
316  while( it != mList.end() )
317  {
318  Piece* piece = &*it;
319  dataRange.setEndByWidth( piece->width() );
320 
321  if( dataRange.includes(firstStart) )
322  {
323  // piece does not start at offset?
324  if( dataRange.start() < firstStart )
325  {
326  // well, split and insert second piece, even if we move it later, just make it work for now
327  const Piece secondPiece = piece->splitAtLocal( dataRange.localIndex(firstStart) );
328  it = mList.insert( ++it, secondPiece );
329  piece = &*it;
330  dataRange.setStart( firstStart );
331  }
332  QLinkedList<Piece>::Iterator firstIt = it;
333 
334  do
335  {
336  if( dataRange.includes(secondRange.start()) )
337  {
338  // piece does not start at source?
339  if( dataRange.start() < secondRange.start() )
340  {
341  // well, split and insert second piece, even if we move it later, just make it work for now
342  const Piece secondPiece = piece->splitAtLocal( dataRange.localIndex(secondRange.start()) );
343  it = mList.insert( ++it, secondPiece );
344  piece = &*it;
345  dataRange.setStart( secondRange.start() );
346  }
347  QLinkedList<Piece>::Iterator firstSecondIt = it;
348 
349  do
350  {
351  if( dataRange.includes(secondRange.end()) )
352  {
353  // piece does not start at source?
354  if( secondRange.end() < dataRange.end() )
355  {
356  // well, split and insert second piece, even if we move it later, just make it work for now
357  const Piece secondPiece = piece->splitAtLocal( dataRange.localIndex(secondRange.nextBehindEnd()) );
358  it = mList.insert( ++it, secondPiece );
359  }
360  else
361  ++it;
362  QLinkedList<Piece>::Iterator behindLastSecondIt = it;
363 
364  for( it=firstSecondIt; it!=behindLastSecondIt; ++it )
365  {
366  firstIt = mList.insert( firstIt, *it ) + 1;
367  }
368  mList.erase( firstSecondIt, behindLastSecondIt );
369 
370  // done, move out of here
371  it = mList.end();
372  break;
373  }
374  dataRange.setStart( dataRange.nextBehindEnd() );
375  ++it;
376 
377  // removeRange is longer than content TODO: just quit or at least remove till the end?
378  if( it == mList.end() )
379  break;
380  piece = &*it;
381  dataRange.setEndByWidth( piece->width() );
382  }
383  while( it != mList.end() );
384  }
385  else
386  {
387  dataRange.setStart( dataRange.nextBehindEnd() );
388  ++it;
389 
390  // removeRange is longer than content TODO: just quit or at least remove till the end?
391  if( it == mList.end() )
392  break;
393  piece = &*it;
394  dataRange.setEndByWidth( piece->width() );
395  }
396  }
397  while( it != mList.end() );
398  break;
399  }
400 
401  dataRange.setStart( dataRange.nextBehindEnd() );
402  ++it;
403  }
404 }
405 
406 Piece PieceTable::replaceOne( Address dataOffset, Address storageOffset, int storageId )
407 {
408  int replacedStorageId = Piece::OriginalStorage;
409  Address replacedStorageOffset = -1;
410 
411  QMutableLinkedListIterator<Piece> it( mList );
412 
413  AddressRange dataRange( 0, -1 );
414  while( it.hasNext() )
415  {
416  Piece* piece = &it.peekNext();
417  dataRange.setEndByWidth( piece->width() );
418  if( dataRange.includes(dataOffset) )
419  {
420  replacedStorageId = piece->storageId();
421 
422  const Piece replacePiece( storageOffset, 1, storageId );
423  // piece starts at offset?
424  if( dataRange.start() == dataOffset )
425  {
426  replacedStorageOffset = piece->start();
427  if( dataRange.width() == 1 )
428  {
429  piece->set( storageOffset, storageOffset );
430  piece->setStorageId( storageId );
431  }
432  else
433  {
434  it.insert( replacePiece );
435  piece->moveStartBy( 1 );
436  }
437  }
438  else if( dataRange.end() == dataOffset )
439  {
440  replacedStorageOffset = piece->end();
441  piece->moveEndBy( -1 );
442  it.next();
443  it.insert( replacePiece );
444  }
445  else
446  {
447  const Address localIndex = dataRange.localIndex( dataOffset );
448  replacedStorageOffset = piece->start() + localIndex;
449 
450  const Piece secondPiece = piece->removeLocal( AddressRange::fromWidth(localIndex,1) );
451  it.next();
452  it.insert( replacePiece );
453  it.insert( secondPiece );
454  }
455  break;
456  }
457  it.next();
458  dataRange.setStart( dataRange.nextBehindEnd() );
459  }
460  return Piece( replacedStorageOffset, 1, replacedStorageId );
461 }
462 
463 }
KDE::Range::includesInside
bool includesInside(T Value) const
returns true if Value is covered and not at a side
Definition: range.h:95
KPieceTable::PieceTable::replace
PieceList replace(const AddressRange &removeRange, Size insertLength, Address storageOffset)
Definition: piecetable.cpp:299
KPieceTable::Piece::subPiece
Piece subPiece(const AddressRange &local) const
Definition: piece.h:116
KDE::Range::moveStartBy
void moveStartBy(T D)
moves the start by D.
Definition: range.h:78
KPieceTable::PieceList::append
void append(const PieceList &other)
Definition: piecelist.h:81
KPieceTable::Size
Okteta::Size Size
Definition: piece.h:33
KPieceTable::Piece::splitAtLocal
Piece splitAtLocal(Address localStorageOffset)
Definition: piece.h:91
KDE::NumberRange::nextBehindEnd
N nextBehindEnd() const
Definition: numberrange.h:145
KDE::NumberRange< Address, Size >
KDE::NumberRange::localRange
NumberRange localRange(const NumberRange &other) const
Definition: numberrange.h:201
KDE::Range::start
T start() const
Definition: range.h:86
KPieceTable::Piece::OriginalStorage
Definition: piece.h:42
KPieceTable::Piece::removeLocal
Piece removeLocal(const AddressRange &localRemoveStorageRange)
Definition: piece.h:99
KPieceTable::PieceTable::PieceTable
PieceTable(Size size=0)
Definition: piecetable.cpp:32
KPieceTable::PieceTable::getStorageData
bool getStorageData(int *storageId, Address *storageOffset, Address dataOffset) const
Definition: piecetable.cpp:47
KPieceTable::Piece::append
bool append(const Piece &other)
Definition: piece.h:126
KPieceTable::PieceTable::size
Size size() const
Definition: piecetable.h:64
KDE::NumberRange::width
S width() const
Definition: numberrange.h:141
KPieceTable::PieceList::size
int size() const
Definition: piecelist.h:67
QLinkedList
KPieceTable::PieceList
Definition: piecelist.h:35
KPieceTable::PieceTable::mSize
Size mSize
Definition: piecetable.h:61
KDE::NumberRange::localIndex
N localIndex(N index) const
Definition: numberrange.h:199
KPieceTable::PieceList::isEmpty
bool isEmpty() const
Definition: piecelist.h:68
KDE::Range::end
T end() const
Definition: range.h:88
KPieceTable::Piece::ChangeStorage
Definition: piece.h:43
KDE::NumberRange< Address, Size >::fromWidth
static NumberRange fromWidth(AddressstartIndex, Sizewidth)
constructs a range by width
KPieceTable::Piece::removeStartBeforeLocal
Piece removeStartBeforeLocal(Address storageOffset)
Definition: piece.h:103
KPieceTable::PieceTable::swap
void swap(Address firstStart, const AddressRange &secondRange)
Definition: piecetable.cpp:311
KPieceTable::PieceTable::replaceOne
Piece replaceOne(Address dataOffset, Address storageOffset, int storageId=Piece::ChangeStorage)
Definition: piecetable.cpp:406
KPieceTable::Address
Okteta::Address Address
Definition: piece.h:34
KDE::NumberRange::setEndByWidth
void setEndByWidth(S width)
sets the last index of the range's range to be width-1 behind the start If the range is invalid the b...
Definition: numberrange.h:152
KPieceTable::PieceList::at
const Piece & at(int i) const
Definition: piecelist.h:70
KDE::Range::includes
bool includes(T Value) const
returns true if Value is covered
Definition: range.h:93
KPieceTable::Piece
Definition: piece.h:38
KPieceTable::Piece::prepend
bool prepend(const Piece &other)
Definition: piece.h:121
KPieceTable::PieceTable::init
void init(Size size)
Definition: piecetable.cpp:37
KPieceTable::PieceList::totalLength
Size totalLength() const
Definition: piecelist.h:69
KPieceTable::Piece::storageId
int storageId() const
Definition: piece.h:83
KPieceTable::PieceTable::mList
QLinkedList< Piece > mList
Definition: piecetable.h:60
KPieceTable::PieceTable::remove
PieceList remove(const AddressRange &removeRange)
Definition: piecetable.cpp:192
piecetable.h
KPieceTable::Piece::setStorageId
void setStorageId(int storageId)
Definition: piece.h:85
KDE::Range::setStart
void setStart(T S)
sets the first index of the range
Definition: range.h:58
KPieceTable::Piece::remove
Piece remove(const AddressRange &removeStorageRange)
Definition: piece.h:95
KDE::Range::isValid
bool isValid() const
returns true if the range covers at least one index
Definition: range.h:122
KPieceTable::PieceTable::insert
void insert(Address insertDataOffset, Size insertLength, Address storageOffset)
Definition: piecetable.cpp:73
KDE::Range::moveEndBy
void moveEndBy(T D)
moves the end by D.
Definition: range.h:80
KPieceTable::Piece::removeEndBehindLocal
Piece removeEndBehindLocal(Address storageOffset)
Definition: piece.h:109
KDE::Range::set
void set(T S, T E)
sets the first and the last index of the range
Definition: range.h:54
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:04:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

okteta

Skip menu "okteta"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal