~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/plugins/grass/qtermwidget/BlockArray.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of Konsole, an X terminal.
 
3
    Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
 
4
 
 
5
    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
 
6
 
 
7
    This program is free software; you can redistribute it and/or modify
 
8
    it under the terms of the GNU General Public License as published by
 
9
    the Free Software Foundation; either version 2 of the License, or
 
10
    (at your option) any later version.
 
11
 
 
12
    This program is distributed in the hope that it will be useful,
 
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
    GNU General Public License for more details.
 
16
 
 
17
    You should have received a copy of the GNU General Public License
 
18
    along with this program; if not, write to the Free Software
 
19
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
20
    02110-1301  USA.
 
21
 
 
22
*/
 
23
 
 
24
// Own
 
25
#include "BlockArray.h"
 
26
 
 
27
#include <QtCore>
 
28
 
 
29
// System
 
30
#include <assert.h>
 
31
#include <sys/mman.h>
 
32
#include <sys/param.h>
 
33
#include <unistd.h>
 
34
#include <stdio.h>
 
35
 
 
36
 
 
37
using namespace Konsole;
 
38
 
 
39
static int blocksize = 0;
 
40
 
 
41
BlockArray::BlockArray()
 
42
    : size( 0 ),
 
43
    current( size_t( -1 ) ),
 
44
    index( size_t( -1 ) ),
 
45
    lastmap( 0 ),
 
46
    lastmap_index( size_t( -1 ) ),
 
47
    lastblock( 0 ), ion( -1 ),
 
48
    length( 0 )
 
49
{
 
50
  // lastmap_index = index = current = size_t(-1);
 
51
  if ( blocksize == 0 )
 
52
    blocksize = (( sizeof( Block ) / getpagesize() ) + 1 ) * getpagesize();
 
53
 
 
54
}
 
55
 
 
56
BlockArray::~BlockArray()
 
57
{
 
58
  setHistorySize( 0 );
 
59
  assert( !lastblock );
 
60
}
 
61
 
 
62
size_t BlockArray::append( Block *block )
 
63
{
 
64
  if ( !size )
 
65
    return size_t( -1 );
 
66
 
 
67
  ++current;
 
68
  if ( current >= size ) current = 0;
 
69
 
 
70
  int rc;
 
71
  rc = lseek( ion, current * blocksize, SEEK_SET ); if ( rc < 0 ) { perror( "HistoryBuffer::add.seek" ); setHistorySize( 0 ); return size_t( -1 ); }
 
72
  rc = write( ion, block, blocksize ); if ( rc < 0 ) { perror( "HistoryBuffer::add.write" ); setHistorySize( 0 ); return size_t( -1 ); }
 
73
 
 
74
  length++;
 
75
  if ( length > size ) length = size;
 
76
 
 
77
  ++index;
 
78
 
 
79
  delete block;
 
80
  return current;
 
81
}
 
82
 
 
83
size_t BlockArray::newBlock()
 
84
{
 
85
  if ( !size )
 
86
    return size_t( -1 );
 
87
  append( lastblock );
 
88
 
 
89
  lastblock = new Block();
 
90
  return index + 1;
 
91
}
 
92
 
 
93
Block *BlockArray::lastBlock() const
 
94
{
 
95
  return lastblock;
 
96
}
 
97
 
 
98
bool BlockArray::has( size_t i ) const
 
99
{
 
100
  if ( i == index + 1 )
 
101
    return true;
 
102
 
 
103
  if ( i > index )
 
104
    return false;
 
105
  if ( index - i >= length )
 
106
    return false;
 
107
  return true;
 
108
}
 
109
 
 
110
const Block* BlockArray::at( size_t i )
 
111
{
 
112
  if ( i == index + 1 )
 
113
    return lastblock;
 
114
 
 
115
  if ( i == lastmap_index )
 
116
    return lastmap;
 
117
 
 
118
  if ( i > index )
 
119
  {
 
120
    qDebug() << "BlockArray::at() i > index\n";
 
121
    return 0;
 
122
  }
 
123
 
 
124
//     if (index - i >= length) {
 
125
//         kDebug(1211) << "BlockArray::at() index - i >= length\n";
 
126
//         return 0;
 
127
//     }
 
128
 
 
129
  size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
 
130
 
 
131
  assert( j < size );
 
132
  unmap();
 
133
 
 
134
  Block *block = ( Block* )mmap( 0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize );
 
135
 
 
136
  if ( block == ( Block* ) - 1 ) { perror( "mmap" ); return 0; }
 
137
 
 
138
  lastmap = block;
 
139
  lastmap_index = i;
 
140
 
 
141
  return block;
 
142
}
 
143
 
 
144
void BlockArray::unmap()
 
145
{
 
146
  if ( lastmap )
 
147
  {
 
148
    int res = munmap(( char* )lastmap, blocksize );
 
149
    if ( res < 0 ) perror( "munmap" );
 
150
  }
 
151
  lastmap = 0;
 
152
  lastmap_index = size_t( -1 );
 
153
}
 
154
 
 
155
bool BlockArray::setSize( size_t newsize )
 
156
{
 
157
  return setHistorySize( newsize * 1024 / blocksize );
 
158
}
 
159
 
 
160
bool BlockArray::setHistorySize( size_t newsize )
 
161
{
 
162
//    kDebug(1211) << "setHistorySize " << size << " " << newsize;
 
163
 
 
164
  if ( size == newsize )
 
165
    return false;
 
166
 
 
167
  unmap();
 
168
 
 
169
  if ( !newsize )
 
170
  {
 
171
    delete lastblock;
 
172
    lastblock = 0;
 
173
    if ( ion >= 0 ) close( ion );
 
174
    ion = -1;
 
175
    current = size_t( -1 );
 
176
    return true;
 
177
  }
 
178
 
 
179
  if ( !size )
 
180
  {
 
181
    FILE* tmp = tmpfile();
 
182
    if ( !tmp )
 
183
    {
 
184
      perror( "konsole: cannot open temp file.\n" );
 
185
    }
 
186
    else
 
187
    {
 
188
      ion = dup( fileno( tmp ) );
 
189
      if ( ion < 0 )
 
190
      {
 
191
        perror( "konsole: cannot dup temp file.\n" );
 
192
        fclose( tmp );
 
193
      }
 
194
    }
 
195
    if ( ion < 0 )
 
196
      return false;
 
197
 
 
198
    assert( !lastblock );
 
199
 
 
200
    lastblock = new Block();
 
201
    size = newsize;
 
202
    return false;
 
203
  }
 
204
 
 
205
  if ( newsize > size )
 
206
  {
 
207
    increaseBuffer();
 
208
    size = newsize;
 
209
    return false;
 
210
  }
 
211
  else
 
212
  {
 
213
    decreaseBuffer( newsize );
 
214
    ftruncate( ion, length*blocksize );
 
215
    size = newsize;
 
216
 
 
217
    return true;
 
218
  }
 
219
}
 
220
 
 
221
void moveBlock( FILE *fion, int cursor, int newpos, char *buffer2 )
 
222
{
 
223
  int res = fseek( fion, cursor * blocksize, SEEK_SET );
 
224
  if ( res )
 
225
    perror( "fseek" );
 
226
  res = fread( buffer2, blocksize, 1, fion );
 
227
  if ( res != 1 )
 
228
    perror( "fread" );
 
229
 
 
230
  res = fseek( fion, newpos * blocksize, SEEK_SET );
 
231
  if ( res )
 
232
    perror( "fseek" );
 
233
  res = fwrite( buffer2, blocksize, 1, fion );
 
234
  if ( res != 1 )
 
235
    perror( "fwrite" );
 
236
  //    printf("moving block %d to %d\n", cursor, newpos);
 
237
}
 
238
 
 
239
void BlockArray::decreaseBuffer( size_t newsize )
 
240
{
 
241
  if ( index < newsize ) // still fits in whole
 
242
    return;
 
243
 
 
244
  int offset = ( current - ( newsize - 1 ) + size ) % size;
 
245
 
 
246
  if ( !offset )
 
247
    return;
 
248
 
 
249
  // The Block constructor could do somthing in future...
 
250
  char *buffer1 = new char[blocksize];
 
251
 
 
252
  FILE *fion = fdopen( dup( ion ), "w+b" );
 
253
  if ( !fion )
 
254
  {
 
255
    delete [] buffer1;
 
256
    perror( "fdopen/dup" );
 
257
    return;
 
258
  }
 
259
 
 
260
  int firstblock;
 
261
  if ( current <= newsize )
 
262
  {
 
263
    firstblock = current + 1;
 
264
  }
 
265
  else
 
266
  {
 
267
    firstblock = 0;
 
268
  }
 
269
 
 
270
  size_t oldpos;
 
271
  for ( size_t i = 0, cursor = firstblock; i < newsize; i++ )
 
272
  {
 
273
    oldpos = ( size + cursor + offset ) % size;
 
274
    moveBlock( fion, oldpos, cursor, buffer1 );
 
275
    if ( oldpos < newsize )
 
276
    {
 
277
      cursor = oldpos;
 
278
    }
 
279
    else
 
280
      cursor++;
 
281
  }
 
282
 
 
283
  current = newsize - 1;
 
284
  length = newsize;
 
285
 
 
286
  delete [] buffer1;
 
287
 
 
288
  fclose( fion );
 
289
 
 
290
}
 
291
 
 
292
void BlockArray::increaseBuffer()
 
293
{
 
294
  if ( index < size ) // not even wrapped once
 
295
    return;
 
296
 
 
297
  int offset = ( current + size + 1 ) % size;
 
298
  if ( !offset ) // no moving needed
 
299
    return;
 
300
 
 
301
  // The Block constructor could do somthing in future...
 
302
  char *buffer1 = new char[blocksize];
 
303
  char *buffer2 = new char[blocksize];
 
304
 
 
305
  int runs = 1;
 
306
  int bpr = size; // blocks per run
 
307
 
 
308
  if ( size % offset == 0 )
 
309
  {
 
310
    bpr = size / offset;
 
311
    runs = offset;
 
312
  }
 
313
 
 
314
  FILE *fion = fdopen( dup( ion ), "w+b" );
 
315
  if ( !fion )
 
316
  {
 
317
    perror( "fdopen/dup" );
 
318
    delete [] buffer1;
 
319
    delete [] buffer2;
 
320
    return;
 
321
  }
 
322
 
 
323
  int res;
 
324
  for ( int i = 0; i < runs; i++ )
 
325
  {
 
326
    // free one block in chain
 
327
    int firstblock = ( offset + i ) % size;
 
328
    res = fseek( fion, firstblock * blocksize, SEEK_SET );
 
329
    if ( res )
 
330
      perror( "fseek" );
 
331
    res = fread( buffer1, blocksize, 1, fion );
 
332
    if ( res != 1 )
 
333
      perror( "fread" );
 
334
    int newpos = 0;
 
335
    for ( int j = 1, cursor = firstblock; j < bpr; j++ )
 
336
    {
 
337
      cursor = ( cursor + offset ) % size;
 
338
      newpos = ( cursor - offset + size ) % size;
 
339
      moveBlock( fion, cursor, newpos, buffer2 );
 
340
    }
 
341
    res = fseek( fion, i * blocksize, SEEK_SET );
 
342
    if ( res )
 
343
      perror( "fseek" );
 
344
    res = fwrite( buffer1, blocksize, 1, fion );
 
345
    if ( res != 1 )
 
346
      perror( "fwrite" );
 
347
  }
 
348
  current = size - 1;
 
349
  length = size;
 
350
 
 
351
  delete [] buffer1;
 
352
  delete [] buffer2;
 
353
 
 
354
  fclose( fion );
 
355
 
 
356
}
 
357