diff options
| author | 2010-10-09 00:39:39 +0000 | |
|---|---|---|
| committer | 2010-10-09 00:39:39 +0000 | |
| commit | a3c47f1744f52aeda9b3738d349f1f7ea696d994 (patch) | |
| tree | 51456bc1c1d540f09b0c07c73fed003afc73799e /src | |
| parent | Fix a bug in KviQString::matchString() (diff) | |
| download | KVIrc-a3c47f1744f52aeda9b3738d349f1f7ea696d994.tar.gz KVIrc-a3c47f1744f52aeda9b3738d349f1f7ea696d994.tar.bz2 KVIrc-a3c47f1744f52aeda9b3738d349f1f7ea696d994.zip | |
Add file.writeBytes and $file.readBytes(). Fix a buggie in the parameter processor triggered when array params are requested
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@5048 17fca916-40b9-46aa-a4ea-0a15b648b75c
Diffstat (limited to 'src')
| -rw-r--r-- | src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp | 1 | ||||
| -rw-r--r-- | src/kvirc/kvs/kvi_kvs_parser_lside.cpp | 4 | ||||
| -rw-r--r-- | src/modules/file/libkvifile.cpp | 204 |
3 files changed, 197 insertions, 12 deletions
diff --git a/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp b/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp index c2a123a0d..e1002dc84 100644 --- a/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp +++ b/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp @@ -334,6 +334,7 @@ namespace KviKvsParameterProcessor } else { *((KviKvsArray **)(pFmtArray->pContainer)) = v->array(); } + break; case KVS_PT_BOOL: // this never fails: anything is converted to a boolean *((bool *)(pFmtArray->pContainer)) = v->asBoolean(); diff --git a/src/kvirc/kvs/kvi_kvs_parser_lside.cpp b/src/kvirc/kvs/kvi_kvs_parser_lside.cpp index 771b99c81..0d981c8e8 100644 --- a/src/kvirc/kvs/kvi_kvs_parser_lside.cpp +++ b/src/kvirc/kvs/kvi_kvs_parser_lside.cpp @@ -470,7 +470,9 @@ end_of_the_param: <search pattern> may contain parentheses to capture parts of the matched text. <replacement string> can contain the escape sequences \\N where N is a number between 1 and 9 to be replaced by the captured text.[br] - (We use \\N because KVIrc will first unquote the string when parsing...)[br] + Please note that you need to double the backslashes in the search pattern + since the KVS parser will first unquote the string and then pass it to the regexp engine. + That's also why we use \\N and not \N.[br] \\0 is a special escape that will be replaced by the entire match (is always valid!).[br] [flags] may be a combination of the letters 'g','i' and 'w'.[br] 'g' causes the search to be global and not stop after the first occurence of <search pattern>.[br] diff --git a/src/modules/file/libkvifile.cpp b/src/modules/file/libkvifile.cpp index d4889f1ea..7add9a938 100644 --- a/src/modules/file/libkvifile.cpp +++ b/src/modules/file/libkvifile.cpp @@ -202,7 +202,7 @@ static bool file_kvs_cmd_delimagepath(KviKvsModuleCommandCall * c) @keyterms: writing data to files @short: - Writes an ascii data string to a file + Writes character data string to a file @syntax: file.write [-a] [-l] <filename:string> <data:string> @switches: @@ -212,14 +212,16 @@ static bool file_kvs_cmd_delimagepath(KviKvsModuleCommandCall * c) Causes the file to be written in the local 8 bit character set instead of the default utf8. @description: - Writes <data> (which is an ASCII string) to the file <filename>.[br] + Writes <data> (which is a string of characters) to the file <filename>.[br] It does NOT append a traling LF character: if you want it you must explicitly specify it in the <data> parameter.[br] -a causes the command to append the <data> to the file instead of overwriting the entire file.[br] The path is adjusted according to the system that KVIrc is running on so you don't have to bother about portability: it *should* be automatically guaranteed. Just use UNIX style paths for them.[br] The file is saved in utf8 unless the -l switch is specified (in that case the local 8 bit encoding is used). - Please note that uf8 is the only character set that preserves ALL the possible characters. + Please note that utf8 is the only character set that preserves ALL the possible characters + with the exception of the null terminator. If you want to write binary data + take a look at [fnc]$file.writeBytes[/cmd] instead. @seealso: [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc] */ @@ -245,6 +247,84 @@ static bool file_kvs_cmd_write(KviKvsModuleCommandCall * c) } /* + @doc: file.writeBytes + @type: + command + @title: + file.writeBytes + @keyterms: + writing data to files + @short: + Writes binary data string to a file + @syntax: + file.writeBytes [-a] <filename:string> <dataArray:array> + @switches: + !sw: -a | --append + If the file already exists, append the data instead of overwriting the original contents. + @description: + Writes <dataArray> (which must be an array) to the file <filename>.[br] + The array should either contain integers between 0 and 255, which will be written as bytes, + or strings, which will be written in utf8 encoding. + -a causes the command to append the <data> to the file instead of overwriting the entire file.[br] + The path is adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use UNIX style paths for them.[br] + @examples: + [example] + for(%i=0;%i<256;%i++) + %a[%i] = %i + file.writeBytes "/home/pragma/test.bin" %a + [/example] + @seealso: + [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc], [fnc]$file.write[/fnc] +*/ +static bool file_kvs_cmd_writeBytes(KviKvsModuleCommandCall * c) +{ + QString szFileName; + KviKvsArray * pArray = NULL; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName) + KVSM_PARAMETER("dataArray",KVS_PT_ARRAY,0,pArray) + KVSM_PARAMETERS_END(c) + + KviFileUtils::adjustFilePath(szFileName); + + if(!pArray) + return c->error(__tr2qs("Missing data array")); + + KviFile f(szFileName); + if(!f.open(QFile::WriteOnly | (c->switches()->find('a',"append") ? QFile::Append : QFile::Truncate))) + { + c->warning(__tr2qs("Can't open file %1 for writing").arg(szFileName)); + return true; + } + + QByteArray aBuffer; + + for(kvs_uint_t i=0;i<pArray->size();i++) + { + KviKvsVariant * pData = pArray->at(i); + kvs_int_t iValue; + if(pData->asInteger(iValue)) + { + aBuffer.append((char)iValue); + } else { + QString szValue; + pData->asString(szValue); + aBuffer.append(szValue.toUtf8()); + } + } + + if(!aBuffer.data()) + return true; // nothing to do + if(f.write(aBuffer.data(),aBuffer.length()) != ((unsigned int)(aBuffer.length()))) + c->warning(__tr2qs("Error writing bytes to file %1").arg(szFileName)); + + return true; +} + +/* @doc: file.rename @type: command @@ -704,6 +784,7 @@ static bool file_kvs_fnc_ls(KviKvsModuleFunctionCall * c) expect strange results.[br] If <size> is not specified, then KVIrc tries to read the whole file up to the 1 MiB limit (so if you want to read a file that is bigger thatn 1 MiB then you MUST specify the <size>).[br] + If you want read binary data (with null bytes inside) then take a look at [fnc]$file.readBytes[/fnc]. WARNING: always check the file size before attemting to read a whole file... reading a CDROM iso image may sit down your system :) (and will prolly crash while allocating memory, before attempting to read anything)[br] @@ -717,7 +798,7 @@ static bool file_kvs_fnc_ls(KviKvsModuleFunctionCall * c) echo $file.read(/proc/cpuinfo) [/example] @seealso: - [fnc]$file.readbinary[/fnc] + [fnc]$file.readBytes[/fnc] */ static bool file_kvs_fnc_read(KviKvsModuleFunctionCall * c) { @@ -746,14 +827,96 @@ static bool file_kvs_fnc_read(KviKvsModuleFunctionCall * c) while((uReaded < uSize) && (!f.atEnd())) { + if(uRetries > 1000) + { + // ops + kvi_free(buf); + c->warning(__tr2qs("Read error for file %Q (have been unable to read the requested size in 1000 retries)"),&szNameZ); + return true; + } + int readedNow = f.read(buf + uReaded,uSize - uReaded); + if(readedNow < 0) { kvi_free(buf); c->warning(__tr2qs("Read error for file %Q"),&szNameZ); return true; - } else readedNow += uReaded; - uRetries ++; + } + + uReaded += readedNow; + uRetries++; + } + + buf[uReaded] = '\0'; + + if(szFlags.indexOf('l',Qt::CaseInsensitive) == -1) + c->returnValue()->setString(QString::fromUtf8(buf)); + else + c->returnValue()->setString(QString::fromLocal8Bit(buf)); + + kvi_free(buf); + + return true; +} + +/* + @doc: file.readBytes + @type: + function + @title: + $file.readBytes + @short: + Reads a binary file + @syntax: + <array> $file.read(<filename:string>[,<size:integer>]) + @description: + Reads at most <size> bytes of the file pointed by <filename> + and returns it as an array of integers (bytes). + <size> is an upper limit but may be not reached if the real file is smaller.[br] + If <size> is not specified, then KVIrc tries to read + the whole file up to the 1 MiB limit (so if you want to read a file that is + bigger thatn 1 MiB then you MUST specify the <size>).[br] + If you want simple text data then take a look at [fnc]$file.read[/fnc]. + WARNING: always check the file size before attemting to read a whole file... + reading a CDROM iso image may sit down your system :) (and will prolly crash while + allocating memory, before attempting to read anything)[br] + An empty array (or just "nothing") is returned if a serious error occures.[br] + The <filename> is adjusted according to the system that KVIrc is running on.[br] + @examples: + [example] + echo $file.readBytes(/proc/cpuinfo) + [/example] + @seealso: + [fnc]$file.read[/fnc], [cmd]file.writeBytes[/cmd] +*/ +static bool file_kvs_fnc_readBytes(KviKvsModuleFunctionCall * c) +{ + QString szNameZ; + kvs_uint_t uSize; + QString szFlags; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szNameZ) + KVSM_PARAMETER("size",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szNameZ); + + QFile f(szNameZ); + if(!f.open(QIODevice::ReadOnly)) + { + c->warning(__tr2qs("Can't open the file \"%Q\" for reading"),&szNameZ); + return true; + } + + if(c->params()->count() < 2) + uSize = 1024 * 1024; // 1 meg file default + + unsigned char * buf = (unsigned char *)kvi_malloc(sizeof(char) * (uSize + 1)); + unsigned int uReaded = 0; + unsigned int uRetries = 0; + + while((uReaded < uSize) && (!f.atEnd())) + { if(uRetries > 1000) { // ops @@ -761,15 +924,32 @@ static bool file_kvs_fnc_read(KviKvsModuleFunctionCall * c) c->warning(__tr2qs("Read error for file %Q (have been unable to read the requested size in 1000 retries)"),&szNameZ); return true; } + + int readedNow = f.read((char *)(buf + uReaded),uSize - uReaded); + + if(readedNow < 0) + { + kvi_free(buf); + c->warning(__tr2qs("Read error for file %Q"),&szNameZ); + return true; + } + uReaded += readedNow; + uRetries++; } - buf[uReaded] = '\0'; + KviKvsArray * pArray = new KviKvsArray(); - if(szFlags.indexOf('l',Qt::CaseInsensitive) == -1) - c->returnValue()->setString(QString::fromUtf8(buf)); - else - c->returnValue()->setString(QString::fromLocal8Bit(buf)); + kvs_uint_t u = 0; + unsigned char * p = buf; + while(u < uReaded) + { + pArray->set(u,new KviKvsVariant((kvs_int_t)(*p))); + u++; + p++; + } + + c->returnValue()->setArray(pArray); kvi_free(buf); @@ -1348,6 +1528,7 @@ static bool file_module_init(KviModule * m) KVSM_REGISTER_SIMPLE_COMMAND(m,"rename",file_kvs_cmd_rename); KVSM_REGISTER_SIMPLE_COMMAND(m,"rmdir",file_kvs_cmd_rmdir); KVSM_REGISTER_SIMPLE_COMMAND(m,"write",file_kvs_cmd_write); + KVSM_REGISTER_SIMPLE_COMMAND(m,"writeBytes",file_kvs_cmd_writeBytes); KVSM_REGISTER_SIMPLE_COMMAND(m,"writeLines",file_kvs_cmd_writeLines); KVSM_REGISTER_FUNCTION(m,"allsizes",file_kvs_fnc_allSizes); @@ -1363,6 +1544,7 @@ static bool file_module_init(KviModule * m) KVSM_REGISTER_FUNCTION(m,"ls",file_kvs_fnc_ls); KVSM_REGISTER_FUNCTION(m,"ps",file_kvs_fnc_ps); KVSM_REGISTER_FUNCTION(m,"read",file_kvs_fnc_read); + KVSM_REGISTER_FUNCTION(m,"readBytes",file_kvs_fnc_readBytes); KVSM_REGISTER_FUNCTION(m,"readLines",file_kvs_fnc_readLines); KVSM_REGISTER_FUNCTION(m,"rootdir",file_kvs_fnc_rootdir); KVSM_REGISTER_FUNCTION(m,"size",file_kvs_fnc_size); |
