source: ogBrowser-Git/qtermwidget/src/BlockArray.cpp

qndtest
Last change on this file was 050d67a, checked in by adelcastillo <adelcastillo@…>, 15 years ago

Ahora el browser tiene consola en vez del output.
Pasado todo el sistema de compilacion a cmake.

git-svn-id: https://opengnsys.es/svn/trunk@408 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 7.4 KB
Line 
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
37using namespace Konsole;
38
39static int blocksize = 0;
40
41BlockArray::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
56BlockArray::~BlockArray()
57{
58    setHistorySize(0);
59    assert(!lastblock);
60}
61
62size_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
83size_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
93Block *BlockArray::lastBlock() const
94{
95    return lastblock;
96}
97
98bool 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
110const 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        qDebug() << "BlockArray::at() i > index\n";
120        return 0;
121    }
122   
123//     if (index - i >= length) {
124//         kDebug(1211) << "BlockArray::at() index - i >= length\n";
125//         return 0;
126//     }
127
128    size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
129
130    assert(j < size);
131    unmap();
132
133    Block *block = (Block*)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
134
135    if (block == (Block*)-1) { perror("mmap"); return 0; }
136
137    lastmap = block;
138    lastmap_index = i;
139
140    return block;
141}
142
143void BlockArray::unmap()
144{
145    if (lastmap) {
146        int res = munmap((char*)lastmap, blocksize);
147        if (res < 0) perror("munmap");
148    }
149    lastmap = 0;
150    lastmap_index = size_t(-1);
151}
152
153bool BlockArray::setSize(size_t newsize)
154{
155    return setHistorySize(newsize * 1024 / blocksize);
156}
157
158bool BlockArray::setHistorySize(size_t newsize)
159{
160//    kDebug(1211) << "setHistorySize " << size << " " << newsize;
161
162    if (size == newsize)
163        return false;
164
165    unmap();
166
167    if (!newsize) {
168        delete lastblock;
169        lastblock = 0;
170        if (ion >= 0) close(ion);
171        ion = -1;
172        current = size_t(-1);
173        return true;
174    }
175
176    if (!size) {
177        FILE* tmp = tmpfile();
178        if (!tmp) {
179            perror("konsole: cannot open temp file.\n");
180        } else {
181            ion = dup(fileno(tmp));
182            if (ion<0) {
183                perror("konsole: cannot dup temp file.\n");
184                fclose(tmp);
185            }
186        }
187        if (ion < 0)
188            return false;
189
190        assert(!lastblock);
191
192        lastblock = new Block();
193        size = newsize;
194        return false;
195    }
196
197    if (newsize > size) {
198        increaseBuffer();
199        size = newsize;
200        return false;
201    } else {
202        decreaseBuffer(newsize);
203        ftruncate(ion, length*blocksize);
204        size = newsize;
205
206        return true;
207    }
208}
209
210void moveBlock(FILE *fion, int cursor, int newpos, char *buffer2)
211{
212    int res = fseek(fion, cursor * blocksize, SEEK_SET);
213    if (res)
214        perror("fseek");
215    res = fread(buffer2, blocksize, 1, fion);
216    if (res != 1)
217        perror("fread");
218
219    res = fseek(fion, newpos * blocksize, SEEK_SET);
220    if (res)
221        perror("fseek");
222    res = fwrite(buffer2, blocksize, 1, fion);
223    if (res != 1)
224        perror("fwrite");
225    //    printf("moving block %d to %d\n", cursor, newpos);
226}
227
228void BlockArray::decreaseBuffer(size_t newsize)
229{
230    if (index < newsize) // still fits in whole
231        return;
232
233    int offset = (current - (newsize - 1) + size) % size;
234
235    if (!offset)
236        return;
237
238    // The Block constructor could do somthing in future...
239    char *buffer1 = new char[blocksize];
240
241    FILE *fion = fdopen(dup(ion), "w+b");
242    if (!fion) {
243        delete [] buffer1;
244        perror("fdopen/dup");
245        return;
246    }
247
248    int firstblock;
249    if (current <= newsize) {
250        firstblock = current + 1;
251    } else {
252        firstblock = 0;
253    }
254
255    size_t oldpos;
256    for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
257        oldpos = (size + cursor + offset) % size;
258        moveBlock(fion, oldpos, cursor, buffer1);
259        if (oldpos < newsize) {
260            cursor = oldpos;
261        } else
262            cursor++;
263    }
264
265    current = newsize - 1;
266    length = newsize;
267
268    delete [] buffer1;
269
270    fclose(fion);
271
272}
273
274void BlockArray::increaseBuffer()
275{
276    if (index < size) // not even wrapped once
277        return;
278
279    int offset = (current + size + 1) % size;
280    if (!offset) // no moving needed
281        return;
282
283    // The Block constructor could do somthing in future...
284    char *buffer1 = new char[blocksize];
285    char *buffer2 = new char[blocksize];
286
287    int runs = 1;
288    int bpr = size; // blocks per run
289
290    if (size % offset == 0) {
291        bpr = size / offset;
292        runs = offset;
293    }
294
295    FILE *fion = fdopen(dup(ion), "w+b");
296    if (!fion) {
297        perror("fdopen/dup");
298        delete [] buffer1;
299        delete [] buffer2;
300        return;
301    }
302
303    int res;
304    for (int i = 0; i < runs; i++)
305    {
306        // free one block in chain
307        int firstblock = (offset + i) % size;
308        res = fseek(fion, firstblock * blocksize, SEEK_SET);
309        if (res)
310            perror("fseek");
311        res = fread(buffer1, blocksize, 1, fion);
312        if (res != 1)
313            perror("fread");
314        int newpos = 0;
315        for (int j = 1, cursor=firstblock; j < bpr; j++)
316        {
317            cursor = (cursor + offset) % size;
318            newpos = (cursor - offset + size) % size;
319            moveBlock(fion, cursor, newpos, buffer2);
320        }
321        res = fseek(fion, i * blocksize, SEEK_SET);
322        if (res)
323            perror("fseek");
324        res = fwrite(buffer1, blocksize, 1, fion);
325        if (res != 1)
326            perror("fwrite");
327    }
328    current = size - 1;
329    length = size;
330
331    delete [] buffer1;
332    delete [] buffer2;
333
334    fclose(fion);
335
336}
337
Note: See TracBrowser for help on using the repository browser.