diff options
Diffstat (limited to 'src/modules/objects/KvsObject_file.cpp')
| -rw-r--r-- | src/modules/objects/KvsObject_file.cpp | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/src/modules/objects/KvsObject_file.cpp b/src/modules/objects/KvsObject_file.cpp new file mode 100644 index 000000000..909b1c552 --- /dev/null +++ b/src/modules/objects/KvsObject_file.cpp @@ -0,0 +1,648 @@ +//============================================================================= +// +// File : KvsObject_file.cpp +// Creation date : Fri Mar 18 21:30:48 CEST 2005 +// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor) +// +// This file is part of the KVIrc irc client distribution +// Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) 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. +// +//============================================================================= + + +#include "KvsObject_file.h" +#include "kvi_debug.h" +#include "KviLocale.h" +#include "KviError.h" +#include "KviFile.h" +#include "KviFileUtils.h" +#include "KvsObject_memoryBuffer.h" + +#include <QStringList> +//#include <QFile> +#include <QTextStream> + +#define CHECK_FILE_IS_OPEN if (!m_pFile->isOpen())\ + {c->warning(__tr2qs_ctx("File is not open!","objects"));return true;} + +// needed for $open() + +const char * const mod_tbl[] = { + "Raw", + "ReadOnly", + "WriteOnly", + "ReadWrite", + "Append", + "Truncate" +}; + +const QIODevice::OpenMode mod_cod[] = { + QIODevice::Unbuffered, + QIODevice::ReadOnly, + QIODevice::WriteOnly, + QIODevice::ReadWrite, + QIODevice::Append, + QIODevice::Truncate +}; + +#define mod_num (sizeof(mod_tbl) / sizeof(mod_tbl[0])) + +/* + @doc: file + @keyterms: + file object class, creating files + @title: + file class + @type: + class + @short: + I/O device that operates on files + @inherits: + [class]object[/class] + @description: + This object class provides access to files - basic I/O + operations, copying, removing etc... + @functions: + !fn: $setName(<file_name:string>) + Sets the file name to <file_name>. It does [b]not move[/b] the file, + it just changes the file the object is "pointing to". You can + not change names of already open files.[br] + See also: [classfnc]$open[/classfnc](), + [classfnc]$name[/classfnc](). + !fn: <string> $name() + Returns name set by [classfnc]$setName[/classfnc]().[br] + See also: [classfnc]$setName[/classfnc](). + !fn: $open(<mode1:string>, <mode2:string>) + Attempts to open the file in specified mode or modes "sum". + Valid modes are:[br] + [pre] + Raw - raw, non-buffered access[br] + ReadOnly - opens the file read-only[br] + WriteOnly - opens the file write-only[br] + ReadWrite - opens the file in read-write mode[br] + Append - opens the file in append mode. The file index is set to the end of the file.[br] + Truncate - truncates the file[br] + [/pre] + If you call this function without any parameters, the file is + opened in ReadOnly mode.[br] + When working with buffered files, data is not written directly + to the file at once. You must call [classfnc]$flush[/classfnc]() to force it.[br] + See also: [classfnc]$close[/classfnc](), + [classfnc]$flush[/classfnc](). + !fn: <boolean> $isOpen() + Returns '1' if the file is open, '0' otherwise. + !fn: $close() + Closes the file, flushing the buffers first.[br] + See also: [classfnc]$flush[/classfnc](). + !fn: $flush() + Flushes the file buffer to disk. Calling this after opening the + file in 'Raw' mode doesn't make much sense.[br] + See also: [classfnc]$open[/classfnc](), + [classfnc]$close[/classfnc](). + !fn: <integer> $size() + Returns current file size. + !fn: <boolean> $atEnd() + Returns '1' if you have reached end of the file, '0' otherwise. + [br]See also: [classfnc]$seek[/classfnc](), + [classfnc]$where[/classfnc](). + !fn: <integer> $where() + Returns current position in the file (file index).[br] + See also: [classfnc]$seek[/classfnc](). + !fn: $seek(<index:integer>) + Sets the file index to <index>.[br] + See also: [classfnc]$where[/classfnc](), + [classfnc]$atEnd[/classfnc](). + !fn: $putch(<char>) + Writes character <char> to the file and increments file + index.[br] + See also: [classfnc]$getch[/classfnc](), + [classfnc]$ungetch[/classfnc](). + !fn: <char> $getch() + Reads a character from the file and increments file index.[br] + See also: [classfnc]$putch[/classfnc](), + [classfnc]$ungetch[/classfnc](). + !fn: $ungetch(<char>) + Puts the character <char> back to the file and + decrements the file index. This is usually called to undo a + $getch() call.[br] + See also: [classfnc]$getch[/classfnc], + [classfnc]$putch[/classfnc](). + !fn: $readLine(<text_line:string>) + Reads a line of text from the file and increments file index. + !fn: $writeLine(<text_line:string>) + Appends a line of text to the end of the file. + $readBlock() + $writeBlock() +*/ + + +KVSO_BEGIN_REGISTERCLASS(KvsObject_file,"file","object") + KVSO_REGISTER_HANDLER(KvsObject_file,"setName",setName) + KVSO_REGISTER_HANDLER(KvsObject_file,"name",name) + + KVSO_REGISTER_HANDLER(KvsObject_file,"open",open) + KVSO_REGISTER_HANDLER(KvsObject_file,"isOpen",isOpen) + KVSO_REGISTER_HANDLER(KvsObject_file,"close",close) + KVSO_REGISTER_HANDLER(KvsObject_file,"flush",flush) + + KVSO_REGISTER_HANDLER(KvsObject_file,"size",size) + KVSO_REGISTER_HANDLER(KvsObject_file,"resize",resize) + + KVSO_REGISTER_HANDLER(KvsObject_file,"atEnd",atEnd) + KVSO_REGISTER_HANDLER(KvsObject_file,"where",where) + KVSO_REGISTER_HANDLER(KvsObject_file,"seek",seek) + + KVSO_REGISTER_HANDLER(KvsObject_file,"putch",putch) + KVSO_REGISTER_HANDLER(KvsObject_file,"getch",getch) + KVSO_REGISTER_HANDLER(KvsObject_file,"ungetch",unGetch) + KVSO_REGISTER_HANDLER(KvsObject_file,"readByte",readByte) + + KVSO_REGISTER_HANDLER(KvsObject_file,"readBlock",readBlock) + KVSO_REGISTER_HANDLER(KvsObject_file,"writeBlock", writeBlock) + + KVSO_REGISTER_HANDLER(KvsObject_file,"readHexBlock",readHexBlock) + KVSO_REGISTER_HANDLER(KvsObject_file,"writeHexBlock",writeHexBlock) + + KVSO_REGISTER_HANDLER(KvsObject_file,"readLine",readLine) + KVSO_REGISTER_HANDLER(KvsObject_file,"writeLine",writeLine) + + KVSO_REGISTER_HANDLER(KvsObject_file,"write",write) + KVSO_REGISTER_HANDLER(KvsObject_file,"read",read) + + +KVSO_END_REGISTERCLASS(KvsObject_file) + + +KVSO_BEGIN_CONSTRUCTOR(KvsObject_file,KvsObject_widget) + m_pFile = new KviFile(); + +KVSO_END_CONSTRUCTOR(KvsObject_file) + +KVSO_BEGIN_DESTRUCTOR(KvsObject_file) + + if (m_pFile) delete m_pFile; + +KVSO_END_CONSTRUCTOR(KvsObject_file) + +KVSO_CLASS_FUNCTION(file,setName) +{ + CHECK_INTERNAL_POINTER(m_pFile) + QString szName; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("file_name",KVS_PT_STRING,0,szName) + KVSO_PARAMETERS_END(c) + m_pFile->setFileName(szName); + return true; +} + +KVSO_CLASS_FUNCTION(file,name) +{ + CHECK_INTERNAL_POINTER(m_pFile) + c->returnValue()->setString(m_pFile->fileName()); + return true; +} + +KVSO_CLASS_FUNCTION(file,open) +{ + CHECK_INTERNAL_POINTER(m_pFile) + QStringList modes; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("file_mode",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,modes) + KVSO_PARAMETERS_END(c) + + if(m_pFile->fileName().isEmpty()) + { + c->warning(__tr2qs_ctx("Empty filename string","objects")); + return true; + } + QIODevice::OpenMode mod,sum; + if (modes.empty()) sum = QIODevice::ReadWrite|QIODevice::Append; // if no parameters given, default to ReadWrite | Append + else + { + for ( int idx=0;idx<modes.count();idx++) + { + int found=false; + for(unsigned int j = 0; j < mod_num; j++) + { + + if(KviQString::equalCI(modes.at(idx), mod_tbl[j])) + { + mod=mod_cod[j]; + found=true; + break; + } + } + if(found) + sum = sum | mod; + else + c->warning(__tr2qs_ctx("No such open mode '%Q'","objects"),&modes.at(idx)); + } + } + c->returnValue()->setBoolean(m_pFile->open(sum)); + return true; +} + +KVSO_CLASS_FUNCTION(file,isOpen) +{ + CHECK_INTERNAL_POINTER(m_pFile) + c->returnValue()->setBoolean(m_pFile->isOpen()); + return true; +} + +KVSO_CLASS_FUNCTION(file,close) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + m_pFile->close(); + return true; +} + +KVSO_CLASS_FUNCTION(file,flush) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + m_pFile->flush(); + return true; +} + +KVSO_CLASS_FUNCTION(file,size) +{ + CHECK_INTERNAL_POINTER(m_pFile) + c->returnValue()->setInteger((kvs_int_t)(m_pFile->size())); + return true; +} + +KVSO_CLASS_FUNCTION(file,atEnd) +{ + CHECK_INTERNAL_POINTER(m_pFile) + c->returnValue()->setInteger((kvs_int_t)(m_pFile->atEnd())); + return true; +} + +KVSO_CLASS_FUNCTION(file,where) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + c->returnValue()->setInteger((kvs_int_t)(m_pFile->pos())); + return true; +} + +KVSO_CLASS_FUNCTION(file,seek) +{ + CHECK_INTERNAL_POINTER(m_pFile) + kvs_uint_t uIndex; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex) + KVSO_PARAMETERS_END(c) + CHECK_FILE_IS_OPEN + m_pFile->seek(uIndex); + return true; +} + + +KVSO_CLASS_FUNCTION(file,resize) +{ + CHECK_INTERNAL_POINTER(m_pFile) + kvs_int_t iSize; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("size",KVS_PT_INTEGER,0,iSize) + KVSO_PARAMETERS_END(c) + CHECK_FILE_IS_OPEN + m_pFile->resize(iSize); + return true; +} + +KVSO_CLASS_FUNCTION(file,putch) +{ + CHECK_INTERNAL_POINTER(m_pFile) + QString szChar; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("char",KVS_PT_STRING,0,szChar) + KVSO_PARAMETERS_END(c) + if (szChar.length()>1)c->warning(__tr2qs_ctx("Argument too long, using only first char","objects")); + const char *ch=szChar.toUtf8().data(); + if (!m_pFile->putChar(ch[0])) c->warning(__tr2qs_ctx("Write error occured!","objects")); + return true; +} + +KVSO_CLASS_FUNCTION(file,getch) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + char ch; + if (!m_pFile->getChar(&ch)) c->warning(__tr2qs_ctx("Read error occured!","objects")); // c->error ? + QString szChar = QChar(ch); + c->returnValue()->setString(szChar); + return true; +} + +KVSO_CLASS_FUNCTION(file,readByte) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + char ch; + if (!m_pFile->getChar(&ch)) c->warning(__tr2qs_ctx("Read error occured!","objects")); // c->error ? + //QString szChar = QChar(ch); + c->returnValue()->setInteger((kvs_int_t) ch); + return true; +} + +KVSO_CLASS_FUNCTION(file,unGetch) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + QString szChar; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("char",KVS_PT_STRING,0,szChar) + KVSO_PARAMETERS_END(c) + if (szChar.length()>1) c->warning(__tr2qs_ctx("Argument too long, using only the first char","objects")); + const char *ch=szChar.toUtf8().data(); + m_pFile->ungetChar(ch[0]); + return true; +} + +KVSO_CLASS_FUNCTION(file,readBlock) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + kvs_uint_t uLen; + KviKvsObject * pObject; + kvs_hobject_t hObject; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,0,uLen) + KVSO_PARAMETER("hobject",KVS_PT_HOBJECT,KVS_PF_OPTIONAL,hObject) + KVSO_PARAMETERS_END(c) + if (uLen>(kvs_uint_t)m_pFile->size()) uLen=m_pFile->size(); + if (hObject) + { + pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject); + if (!pObject) + { + c->warning(__tr2qs_ctx("Buffer parameter is not an object","objects")); + return true; + } + if (!pObject->inheritsClass("memorybuffer")) + { + c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object","objects")); + return true; + } + //m_pFile->flush(); + ((KvsObject_memoryBuffer *)pObject)->pBuffer()->append(m_pFile->read(uLen)); + return true; + } + else + { + char * buff = new char[uLen + 1]; + //m_pFile->flush(); // advice from QFile man page (to avoid trash) + int rlen = m_pFile->read(buff, uLen); + buff[rlen] = '\0'; + QString szBlock(buff); + c->returnValue()->setString(szBlock); + } + return true; +} + +KVSO_CLASS_FUNCTION(file,read) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + QString szType; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("type",KVS_PT_STRING,0,szType) + KVSO_PARAMETERS_END(c) + if(KviQString::equalCI(szType, "String")) + { + QString szStr; + m_pFile->load(szStr); + c->returnValue()->setString(szStr); + } + else if(KviQString::equalCI(szType, "Integer")) + { + int iValue; + m_pFile->load(iValue); + c->returnValue()->setInteger(iValue); + } + else if(KviQString::equalCI(szType, "Array")) + { + QString szData; + m_pFile->load(szData); + KviKvsVariant *pVar = KviKvsVariant::unserialize(szData); + if (pVar->isArray()) + c->returnValue()->setArray(pVar->array()); + else + c->warning(__tr2qs_ctx("The incoming data isn't an array","objects")); + } + else if(KviQString::equalCI(szType, "Dict")) + { + QString szData; + m_pFile->load(szData); + KviKvsVariant *pVar = KviKvsVariant::unserialize(szData); + if (pVar->isHash()) + c->returnValue()->setHash(pVar->hash()); + else + c->warning(__tr2qs_ctx("The incoming data isn't a Dictionary","objects")); + } + else if(KviQString::equalCI(szType, "String")) + { + QString szStr; + m_pFile->load(szStr); + c->returnValue()->setString(szStr); + } + else + { + c->warning(__tr2qs_ctx("Unsupported datatype '%Q'","objects"),&szType); + } + return true; +} + +KVSO_CLASS_FUNCTION(file,write) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + KviKvsVariant * pVariantData; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("variant_data",KVS_PT_VARIANT,0,pVariantData) + KVSO_PARAMETERS_END(c) + if (pVariantData->isInteger()) + { + kvs_int_t num; + pVariantData->asInteger(num); + m_pFile->save(num); + } + if (pVariantData->isHash() || pVariantData->isArray() || pVariantData->isString()) + { + QString szTmp; + pVariantData->serialize(szTmp); + m_pFile->save(szTmp); + } + return true; +} + +KVSO_CLASS_FUNCTION(file,writeBlock) +{ + CHECK_INTERNAL_POINTER(m_pFile) + kvs_uint_t uLen; + KviKvsObject * pObject; + KviKvsVariant * pVariantData; + kvs_hobject_t hObject; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("string_or_hobject",KVS_PT_VARIANT,0,pVariantData) + KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen) + KVSO_PARAMETERS_END(c) + if(!m_pFile->isOpen())c->warning(__tr2qs_ctx("File is not open!","objects")); + else + { + if (pVariantData->isHObject()) + { + pVariantData->asHObject(hObject); + pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject); + if (!pObject) + { + c->warning(__tr2qs_ctx("Buffer parameter is not an object","objects")); + return true; + } + if (pObject->inheritsClass("memorybuffer")) + { + if (!uLen) + { + if (((KvsObject_memoryBuffer *)pObject)->pBuffer()->size()) + uLen=((KvsObject_memoryBuffer *)pObject)->pBuffer()->size(); + else + { + c->warning(__tr2qs_ctx("The memoryBuffer object is empty: nothing will be saved","objects")); + } + } + const char *pData=((KvsObject_memoryBuffer *)pObject)->pBuffer()->data(); + int rlen=m_pFile->write(pData,uLen); + c->returnValue()->setInteger(rlen); + //m_pFile->flush(); + } else { + c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object","objects")); + return true; + } + + } + else + { + if (!pVariantData->isString()){ + c->warning(__tr2qs_ctx("Block parameter must be a string or a memorybuffer object","objects")); + return true; + } + QString szBlock; + pVariantData->asString(szBlock); + const char *block=szBlock.toUtf8().data(); + int rlen = m_pFile->write(block, uLen); + c->returnValue()->setInteger(rlen); + //m_pFile->flush(); + } + } + return true; +} + +KVSO_CLASS_FUNCTION(file,readLine) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + QString buffer; + //bool ok=KviFileUtils::readLine(m_pFile,buffer); + buffer=m_pFile->readLine(); + c->returnValue()->setString(buffer); + return true; +} + +KVSO_CLASS_FUNCTION(file,writeLine) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + QString szLine; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("text_line",KVS_PT_STRING,0,szLine) + KVSO_PARAMETERS_END(c) + QTextStream ts(m_pFile); + ts << szLine; + return true; +} + +KVSO_CLASS_FUNCTION(file,readHexBlock) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + kvs_uint_t uLen; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("lenght",KVS_PT_UNSIGNEDINTEGER,0,uLen) + KVSO_PARAMETERS_END(c) + if (uLen>(kvs_uint_t)m_pFile->size()) uLen=m_pFile->size(); + char * buff = new char[uLen]; + char * str = new char [(uLen*2)+1]; + m_pFile->flush(); // advice from QFile man page (to avoid trash) + int rlen = m_pFile->read(buff, uLen); + int index=0; + unsigned char byte,msb,lsb=0; + for (int i=0;i<rlen;i++) + { + byte=(unsigned char)buff[i]; + lsb=byte & 0x0f; + msb=byte>>4; + msb>9?msb+='7':msb+='0'; + lsb>9?lsb+='7':lsb+='0'; + str[index++]=msb; + str[index++]=lsb; + } + str[index]='\0'; + c->returnValue()->setString(str); + delete[] str; + delete[] buff; + return true; +} + +KVSO_CLASS_FUNCTION(file,writeHexBlock) +{ + CHECK_INTERNAL_POINTER(m_pFile) + CHECK_FILE_IS_OPEN + QString szBlock; + kvs_uint_t uLen; + KVSO_PARAMETERS_BEGIN(c) + KVSO_PARAMETER("text_block",KVS_PT_STRING,0,szBlock) + KVSO_PARAMETER("lenght",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen) + KVSO_PARAMETERS_END(c) + if (szBlock.length()%2) + { + c->warning(__tr2qs_ctx("Length of hex string is not multiple of 2","objects")); + return true; + } + if (uLen>((uint)szBlock.length()/2)|| !uLen) uLen=szBlock.length(); + else uLen*=2; + unsigned char byte,lsb,msb; + for(unsigned int i=0;i<uLen;i+=2) + { + msb=szBlock.at(i).toAscii(); + lsb=szBlock.at(i+1).toAscii(); + + if (((msb>='A' && msb<='F')||(msb>='0' && msb<='9')) && ((lsb>='A' && lsb<='F')|| (lsb>='0' && lsb<='9'))) + { + msb>='A'?msb-='7':msb-='0'; + lsb>='A'?lsb-='7':lsb-='0'; + } else{ + c->warning(__tr2qs_ctx("The hex string is not correct!","objects")); + return true; + } + byte=(msb*16)+lsb; + m_pFile->putChar(byte); + } + c->returnValue()->setInteger(uLen/2); + return true; +} |
