Mercurial > hg > octave-avbm
view gui/src/terminal/BlockArray.cpp @ 13506:c70511cf64ee
Reformatted to GNU Style.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Sun, 17 Jul 2011 22:59:28 +0200 |
parents | 86d6c3b90ad7 |
children |
line wrap: on
line source
/* This file is part of Konsole, an X terminal. Copyright 2000 by Stephan Kulow <coolo@kde.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "BlockArray.h" // System #include <assert.h> #include <sys/mman.h> #include <sys/param.h> #include <unistd.h> #include <stdio.h> #define KDE_fseek ::fseek #define KDE_lseek ::lseek static int blocksize = 0; BlockArray::BlockArray ():size (0), current (size_t (-1)), index (size_t (-1)), lastmap (0), lastmap_index (size_t (-1)), lastblock (0), ion (-1), length (0) { // lastmap_index = index = current = size_t(-1); if (blocksize == 0) blocksize = ((sizeof (Block) / getpagesize ()) + 1) * getpagesize (); } BlockArray::~BlockArray () { setHistorySize (0); assert (!lastblock); } size_t BlockArray::append (Block * block) { if (!size) return size_t (-1); ++current; if (current >= size) current = 0; int rc; rc = KDE_lseek (ion, current * blocksize, SEEK_SET); if (rc < 0) { perror ("HistoryBuffer::add.seek"); setHistorySize (0); return size_t (-1); } rc = write (ion, block, blocksize); if (rc < 0) { perror ("HistoryBuffer::add.write"); setHistorySize (0); return size_t (-1); } length++; if (length > size) length = size; ++index; delete block; return current; } size_t BlockArray::newBlock () { if (!size) return size_t (-1); append (lastblock); lastblock = new Block (); return index + 1; } Block * BlockArray::lastBlock () const { return lastblock; } bool BlockArray::has (size_t i) const { if (i == index + 1) return true; if (i > index) return false; if (index - i >= length) return false; return true; } const Block * BlockArray::at (size_t i) { if (i == index + 1) return lastblock; if (i == lastmap_index) return lastmap; if (i > index) { //kDebug(1211) << "BlockArray::at() i > index\n"; return 0; } // if (index - i >= length) { // kDebug(1211) << "BlockArray::at() index - i >= length\n"; // return 0; // } size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ; assert (j < size); unmap (); Block *block = (Block *) mmap (0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize); if (block == (Block *) - 1) { perror ("mmap"); return 0; } lastmap = block; lastmap_index = i; return block; } void BlockArray::unmap () { if (lastmap) { int res = munmap ((char *) lastmap, blocksize); if (res < 0) perror ("munmap"); } lastmap = 0; lastmap_index = size_t (-1); } bool BlockArray::setSize (size_t newsize) { return setHistorySize (newsize * 1024 / blocksize); } bool BlockArray::setHistorySize (size_t newsize) { // kDebug(1211) << "setHistorySize " << size << " " << newsize; if (size == newsize) return false; unmap (); if (!newsize) { delete lastblock; lastblock = 0; if (ion >= 0) close (ion); ion = -1; current = size_t (-1); return true; } if (!size) { FILE *tmp = tmpfile (); if (!tmp) { perror ("konsole: cannot open temp file.\n"); } else { ion = dup (fileno (tmp)); if (ion < 0) { perror ("konsole: cannot dup temp file.\n"); fclose (tmp); } } if (ion < 0) return false; assert (!lastblock); lastblock = new Block (); size = newsize; return false; } if (newsize > size) { increaseBuffer (); size = newsize; return false; } else { decreaseBuffer (newsize); if (ftruncate (ion, length * blocksize) == -1) perror ("ftruncate"); size = newsize; return true; } } void moveBlock (FILE * fion, int cursor, int newpos, char *buffer2) { int res = KDE_fseek (fion, cursor * blocksize, SEEK_SET); if (res) perror ("fseek"); res = fread (buffer2, blocksize, 1, fion); if (res != 1) perror ("fread"); res = KDE_fseek (fion, newpos * blocksize, SEEK_SET); if (res) perror ("fseek"); res = fwrite (buffer2, blocksize, 1, fion); if (res != 1) perror ("fwrite"); } void BlockArray::decreaseBuffer (size_t newsize) { if (index < newsize) // still fits in whole return; int offset = (current - (newsize - 1) + size) % size; if (!offset) return; // The Block constructor could do somthing in future... char *buffer1 = new char[blocksize]; FILE *fion = fdopen (dup (ion), "w+b"); if (!fion) { delete[]buffer1; perror ("fdopen/dup"); return; } int firstblock; if (current <= newsize) { firstblock = current + 1; } else { firstblock = 0; } size_t oldpos; for (size_t i = 0, cursor = firstblock; i < newsize; i++) { oldpos = (size + cursor + offset) % size; moveBlock (fion, oldpos, cursor, buffer1); if (oldpos < newsize) { cursor = oldpos; } else cursor++; } current = newsize - 1; length = newsize; delete[]buffer1; fclose (fion); } void BlockArray::increaseBuffer () { if (index < size) // not even wrapped once return; int offset = (current + size + 1) % size; if (!offset) // no moving needed return; // The Block constructor could do somthing in future... char *buffer1 = new char[blocksize]; char *buffer2 = new char[blocksize]; int runs = 1; int bpr = size; // blocks per run if (size % offset == 0) { bpr = size / offset; runs = offset; } FILE *fion = fdopen (dup (ion), "w+b"); if (!fion) { perror ("fdopen/dup"); delete[]buffer1; delete[]buffer2; return; } int res; for (int i = 0; i < runs; i++) { // free one block in chain int firstblock = (offset + i) % size; res = KDE_fseek (fion, firstblock * blocksize, SEEK_SET); if (res) perror ("fseek"); res = fread (buffer1, blocksize, 1, fion); if (res != 1) perror ("fread"); int newpos = 0; for (int j = 1, cursor = firstblock; j < bpr; j++) { cursor = (cursor + offset) % size; newpos = (cursor - offset + size) % size; moveBlock (fion, cursor, newpos, buffer2); } res = KDE_fseek (fion, i * blocksize, SEEK_SET); if (res) perror ("fseek"); res = fwrite (buffer1, blocksize, 1, fion); if (res != 1) perror ("fwrite"); } current = size - 1; length = size; delete[]buffer1; delete[]buffer2; fclose (fion); }