• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kmemfile.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (C) 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kmemfile.h"
00022 
00023 #include <QtCore/QSharedMemory>
00024 #include <QtCore/QCryptographicHash>
00025 #include <QtCore/QFile>
00026 #include <QtCore/QDir>
00027 
00028 #include "klocalizedstring.h"
00029 
00030 class KMemFile::Private
00031 {
00032 public:
00033   struct sharedInfoData {
00034     int  shmCounter;
00035     qint64 shmDataSize;
00036 
00037     sharedInfoData() {
00038       memset ( this, 0, sizeof ( this ) );
00039     }
00040   };
00041   Private ( KMemFile *_parent ) : readWritePos ( 0 ), shmDataSize ( 0 ), parent ( _parent ) {}
00042 
00043   QString getShmKey ( int iCounter = -1 );
00044   static QString getShmKey ( const QString &filename, int iCounter = -1 );
00045   bool loadContentsFromFile();
00046   void close();
00047 
00048   QString filename;
00049   QSharedMemory shmInfo;
00050   QSharedMemory shmData;
00051   qint64 readWritePos;
00052   qint64 shmDataSize;
00053 
00054   KMemFile *parent;
00055 };
00056 
00057 QString KMemFile::Private::getShmKey ( int iCounter )
00058 {
00059   return getShmKey ( filename, iCounter );
00060 }
00061 
00062 QString KMemFile::Private::getShmKey ( const QString &filename, int iCounter )
00063 {
00064   QByteArray tmp = QString ( QDir ( filename ).canonicalPath() + QString::number ( iCounter ) ).toUtf8();
00065   return QString::fromAscii ( QCryptographicHash::hash ( tmp, QCryptographicHash::Sha1 ) );
00066 }
00067 
00068 bool KMemFile::Private::loadContentsFromFile()
00069 {
00070   QFile f ( filename );
00071   if ( !f.exists() ) {
00072     close();
00073     parent->setErrorString ( i18n ( "File %1 does not exist" , filename ) );
00074     return false;
00075   }
00076   if ( !f.open ( QIODevice::ReadOnly ) ) {
00077     close();
00078     parent->setErrorString ( i18n ( "Cannot open %1 for reading" , filename ) );
00079     return false;
00080   }
00081 
00082   sharedInfoData *infoPtr = static_cast<sharedInfoData*> ( shmInfo.data() );
00083 
00084   infoPtr->shmDataSize = f.size();
00085   shmData.setKey ( getShmKey ( infoPtr->shmCounter ) );
00086   if ( !shmData.create ( infoPtr->shmDataSize ) ) {
00087     close();
00088     parent->setErrorString ( i18n ( "Cannot create memory segment for file %1" , filename ) );
00089     return false;
00090   }
00091   shmData.lock();
00092   qint64 size = 0;
00093   qint64 bytesRead;
00094   char *data = static_cast<char*> ( shmData.data() );
00095   bytesRead = f.read ( data, infoPtr->shmDataSize );
00096   if ( bytesRead != infoPtr->shmDataSize ) {
00097     close();
00098     parent->setErrorString ( i18n ( "Could not read data from %1 into shm" , filename ) );
00099     return false;
00100   }
00101   shmDataSize = size;
00102   shmData.unlock();
00103   return true;
00104 }
00105 
00106 void KMemFile::Private::close()
00107 {
00108   shmData.unlock();
00109   shmData.detach();
00110   shmInfo.unlock();
00111   shmInfo.detach();
00112   readWritePos = 0;
00113   shmDataSize = 0;
00114 }
00115 
00116 KMemFile::KMemFile ( const QString &filename, QObject *parent )
00117     : QIODevice ( parent ), d ( new Private ( this ) )
00118 {
00119   d->filename = filename;
00120 }
00121 
00122 KMemFile::~KMemFile()
00123 {
00124   close();
00125   delete d;
00126 }
00127 
00128 void KMemFile::close ()
00129 {
00130   QIODevice::close();
00131   if ( !isOpen() )
00132     return;
00133   d->close();
00134 }
00135 
00136 bool KMemFile::isSequential () const
00137 {
00138   return false;
00139 }
00140 
00141 bool KMemFile::open ( OpenMode mode )
00142 {
00143   if ( isOpen() ) {
00144     QIODevice::open ( mode );
00145     return false;
00146   }
00147 
00148   if ( mode != QIODevice::ReadOnly ) {
00149     setErrorString ( i18n ( "Only 'ReadOnly' allowed" ) );
00150     return false;
00151   }
00152 
00153   if ( !QFile::exists ( d->filename ) ) {
00154     setErrorString ( i18n ( "File %1 does not exist" , d->filename ) );
00155     return false;
00156   }
00157 
00158   QSharedMemory lock ( QDir ( d->filename ).canonicalPath() );
00159   lock.lock();
00160 
00161   Private::sharedInfoData *infoPtr;
00162   d->shmInfo.setKey ( d->getShmKey() );
00163   // see if it's already in memory
00164   if ( !d->shmInfo.attach ( QSharedMemory::ReadWrite ) ) {
00165     if ( !d->shmInfo.create ( sizeof ( Private::sharedInfoData ) ) ) {
00166       lock.unlock();
00167       setErrorString ( i18n ( "Cannot create memory segment for file %1" , d->filename ) );
00168       return false;
00169     }
00170     d->shmInfo.lock();
00171     // no -> create it
00172     infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
00173     memset ( infoPtr, 0, sizeof ( Private::sharedInfoData ) );
00174     infoPtr->shmCounter = 1;
00175     if ( !d->loadContentsFromFile() ) {
00176       d->shmInfo.unlock();
00177       d->shmInfo.detach();
00178       lock.unlock();
00179       return false;
00180     }
00181   } else {
00182     d->shmInfo.lock();
00183     infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
00184     d->shmData.setKey ( d->getShmKey ( infoPtr->shmCounter ) );
00185     if ( !d->shmData.attach ( QSharedMemory::ReadOnly ) ) {
00186       if ( !d->loadContentsFromFile() ) {
00187         d->shmInfo.unlock();
00188         d->shmInfo.detach();
00189         lock.unlock();
00190         return false;
00191       }
00192     }
00193   }
00194   d->shmDataSize = infoPtr->shmDataSize;
00195   d->shmInfo.unlock();
00196   lock.unlock();
00197 
00198   setOpenMode ( mode );
00199   return true;
00200 }
00201 
00202 bool KMemFile::seek ( qint64 pos )
00203 {
00204   if ( d->shmDataSize < pos ) {
00205     setErrorString ( i18n ( "Cannot seek past eof" ) );
00206     return false;
00207   }
00208   d->readWritePos = pos;
00209   QIODevice::seek ( pos );
00210   return true;
00211 }
00212 
00213 qint64 KMemFile::size () const
00214 {
00215   return d->shmDataSize;
00216 }
00217 
00218 qint64 KMemFile::readData ( char * data, qint64 maxSize )
00219 {
00220   if ( ( openMode() & QIODevice::ReadOnly ) == 0 )
00221     return -1;
00222 
00223   qint64 maxRead = size() - d->readWritePos;
00224   qint64 bytesToRead = qMin ( maxRead, maxSize );
00225   const char *src = static_cast<const char*> ( d->shmData.data() );
00226   memcpy ( data, &src[d->readWritePos], bytesToRead );
00227   d->readWritePos += bytesToRead;
00228   return bytesToRead;
00229 }
00230 
00231 qint64 KMemFile::writeData ( const char *, qint64 )
00232 {
00233   return -1;
00234 }
00235 
00236 void KMemFile::fileContentsChanged ( const QString &filename )
00237 {
00238   QSharedMemory lock ( QDir ( filename ).canonicalPath() );
00239   lock.lock();
00240 
00241   QSharedMemory shmData ( Private::getShmKey ( filename ) );
00242   if ( !shmData.attach() )
00243     return;
00244   shmData.lock();
00245   Private::sharedInfoData *infoPtr = static_cast<Private::sharedInfoData*> ( shmData.data() );
00246   infoPtr->shmCounter++;
00247   infoPtr->shmDataSize = 0;
00248   shmData.unlock();
00249 }

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal