1 //=============================================================================
2 //
3 // File : KvsObject_file.cpp
4 // Creation date : Fri Mar 18 21:30:48 CEST 2005
5 // by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
6 //
7 // This file is part of the KVIrc IRC client distribution
8 // Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net)
9 //
10 // This program is FREE software. You can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // This program is distributed in the HOPE that it will be USEFUL,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 // See the GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, write to the Free Software Foundation,
22 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 //=============================================================================
25
26 #include "KvsObject_file.h"
27 #include "kvi_debug.h"
28 #include "KviLocale.h"
29 #include "KviError.h"
30 #include "KviFile.h"
31 #include "KviFileUtils.h"
32 #include "KvsObject_memoryBuffer.h"
33
34 #include <QStringList>
35 //#include <QFile>
36 #include <QTextStream>
37
38 #define CHECK_FILE_IS_OPEN \
39 if(!m_pFile->isOpen()) \
40 { \
41 c->warning(__tr2qs_ctx("File is not open!", "objects")); \
42 return true; \
43 }
44
45 // needed for $open()
46
47 const char * const mod_tbl[] = {
48 "Raw",
49 "ReadOnly",
50 "WriteOnly",
51 "ReadWrite",
52 "Append",
53 "Truncate"
54 };
55
56 const QIODevice::OpenMode mod_cod[] = {
57 QIODevice::Unbuffered,
58 QIODevice::ReadOnly,
59 QIODevice::WriteOnly,
60 QIODevice::ReadWrite,
61 QIODevice::Append,
62 QIODevice::Truncate
63 };
64
65 #define mod_num (sizeof(mod_tbl) / sizeof(mod_tbl[0]))
66
67 /*
68 @doc: file
69 @keyterms:
70 file object class, creating files
71 @title:
72 file class
73 @type:
74 class
75 @short:
76 I/O device that operates on files
77 @inherits:
78 [class]object[/class]
79 @description:
80 This object class provides access to files - basic I/O
81 operations, copying, removing etc.
82 @functions:
83 !fn: $setName(<file_name:string>)
84 Sets the file name to <file_name>. It does [b]not move[/b] the file,
85 it just changes the file the object is [i]pointing to[/i]. You can
86 not change names of already open files.[br]
87 See also: [classfnc]$open[/classfnc](),
88 [classfnc]$name[/classfnc]().
89 !fn: <string> $name()
90 Returns name set by [classfnc]$setName[/classfnc]().[br]
91 See also: [classfnc]$setName[/classfnc]().
92 !fn: $open(<mode1:string>, <mode2:string>)
93 Attempts to open the file in specified mode or modes [i]sum[/i].
94 Valid modes are:[br]
95 [pre]
96 RAW - RAW, non-buffered access
97 ReadOnly - opens the file read-only
98 WriteOnly - opens the file write-only
99 ReadWrite - opens the file in read-write mode
100 Append - opens the file in append mode. The file index is set to the end of the file.
101 Truncate - truncates the file
102 [/pre]
103 If you call this function without any parameters, the file is
104 opened in read-only mode.[br]
105 When working with buffered files, data is not written directly
106 to the file at once. You must call [classfnc]$flush[/classfnc]() to force it.[br]
107 See also: [classfnc]$close[/classfnc](),
108 [classfnc]$flush[/classfnc]().
109 !fn: <boolean> $isOpen()
110 Returns '1' if the file is open, '0' otherwise.
111 !fn: $close()
112 Closes the file, flushing the buffers first.[br]
113 See also: [classfnc]$flush[/classfnc]().
114 !fn: $flush()
115 Flushes the file buffer to disk. Calling this after opening the
116 file in RAW mode doesn't make much sense.[br]
117 See also: [classfnc]$open[/classfnc](),
118 [classfnc]$close[/classfnc]().
119 !fn: <integer> $size()
120 Returns current file size.
121 !fn: <boolean> $atEnd()
122 Returns '1' if you have reached end of the file, [b]0[/b] otherwise.
123 [br]See also: [classfnc]$seek[/classfnc](),
124 [classfnc]$where[/classfnc]().
125 !fn: <integer> $where()
126 Returns current position in the file (file index).[br]
127 See also: [classfnc]$seek[/classfnc]().
128 !fn: $seek(<index:integer>)
129 Sets the file index to <index>.[br]
130 See also: [classfnc]$where[/classfnc](),
131 [classfnc]$atEnd[/classfnc]().
132 !fn: $putch(<char>)
133 Writes character <char> to the file and increments file
134 index.[br]
135 See also: [classfnc]$getch[/classfnc](),
136 [classfnc]$ungetch[/classfnc]().
137 !fn: <char> $getch()
138 Reads a character from the file and increments file index.[br]
139 See also: [classfnc]$putch[/classfnc](),
140 [classfnc]$ungetch[/classfnc]().
141 !fn: $ungetch(<char>)
142 Puts the character <char> back to the file and
143 decrements the file index. This is usually called to undo a
144 $getch() call.[br]
145 See also: [classfnc]$getch[/classfnc],
146 [classfnc]$putch[/classfnc]().
147 !fn: $readLine(<text_line:string>)
148 Reads a line of text from the file and increments file index.
149 !fn: $writeLine(<text_line:string>)
150 Appends a line of text to the end of the file.
151 $readBlock()
152 $writeBlock()
153 */
154
155 KVSO_BEGIN_REGISTERCLASS(KvsObject_file, "file", "object")
156 KVSO_REGISTER_HANDLER(KvsObject_file, "setName", setName)
157 KVSO_REGISTER_HANDLER(KvsObject_file, "name", name)
158
159 KVSO_REGISTER_HANDLER(KvsObject_file, "open", open)
160 KVSO_REGISTER_HANDLER(KvsObject_file, "isOpen", isOpen)
161 KVSO_REGISTER_HANDLER(KvsObject_file, "close", close)
162 KVSO_REGISTER_HANDLER(KvsObject_file, "flush", flush)
163
164 KVSO_REGISTER_HANDLER(KvsObject_file, "size", size)
165 KVSO_REGISTER_HANDLER(KvsObject_file, "resize", resize)
166
167 KVSO_REGISTER_HANDLER(KvsObject_file, "atEnd", atEnd)
168 KVSO_REGISTER_HANDLER(KvsObject_file, "where", where)
169 KVSO_REGISTER_HANDLER(KvsObject_file, "seek", seek)
170
171 KVSO_REGISTER_HANDLER(KvsObject_file, "putch", putch)
172 KVSO_REGISTER_HANDLER(KvsObject_file, "getch", getch)
173 KVSO_REGISTER_HANDLER(KvsObject_file, "ungetch", unGetch)
174 KVSO_REGISTER_HANDLER(KvsObject_file, "readByte", readByte)
175
176 KVSO_REGISTER_HANDLER(KvsObject_file, "readBlock", readBlock)
177 KVSO_REGISTER_HANDLER(KvsObject_file, "writeBlock", writeBlock)
178
179 KVSO_REGISTER_HANDLER(KvsObject_file, "readHexBlock", readHexBlock)
180 KVSO_REGISTER_HANDLER(KvsObject_file, "writeHexBlock", writeHexBlock)
181
182 KVSO_REGISTER_HANDLER(KvsObject_file, "readLine", readLine)
183 KVSO_REGISTER_HANDLER(KvsObject_file, "writeLine", writeLine)
184
185 KVSO_REGISTER_HANDLER(KvsObject_file, "write", write)
186 KVSO_REGISTER_HANDLER(KvsObject_file, "read", read)
187
188 KVSO_END_REGISTERCLASS(KvsObject_file)
189
190 KVSO_BEGIN_CONSTRUCTOR(KvsObject_file, KvsObject_widget)
191 m_pFile = new KviFile();
192
193 KVSO_END_CONSTRUCTOR(KvsObject_file)
194
195 KVSO_BEGIN_DESTRUCTOR(KvsObject_file)
196
197 if(m_pFile)
198 delete m_pFile;
199
200 KVSO_END_CONSTRUCTOR(KvsObject_file)
201
KVSO_CLASS_FUNCTION(file,setName)202 KVSO_CLASS_FUNCTION(file, setName)
203 {
204 CHECK_INTERNAL_POINTER(m_pFile)
205 QString szName;
206 KVSO_PARAMETERS_BEGIN(c)
207 KVSO_PARAMETER("file_name", KVS_PT_STRING, 0, szName)
208 KVSO_PARAMETERS_END(c)
209 m_pFile->setFileName(szName);
210 return true;
211 }
212
KVSO_CLASS_FUNCTION(file,name)213 KVSO_CLASS_FUNCTION(file, name)
214 {
215 CHECK_INTERNAL_POINTER(m_pFile)
216 c->returnValue()->setString(m_pFile->fileName());
217 return true;
218 }
219
KVSO_CLASS_FUNCTION(file,open)220 KVSO_CLASS_FUNCTION(file, open)
221 {
222 CHECK_INTERNAL_POINTER(m_pFile)
223 QStringList modes;
224 KVSO_PARAMETERS_BEGIN(c)
225 KVSO_PARAMETER("file_mode", KVS_PT_STRINGLIST, KVS_PF_OPTIONAL, modes)
226 KVSO_PARAMETERS_END(c)
227
228 if(m_pFile->fileName().isEmpty())
229 {
230 c->warning(__tr2qs_ctx("Empty filename string", "objects"));
231 return true;
232 }
233 QIODevice::OpenMode mod, sum;
234 if(modes.empty())
235 sum = QIODevice::ReadWrite | QIODevice::Append; // if no parameters given, default to ReadWrite | Append
236 else
237 {
238 for(int idx = 0; idx < modes.count(); idx++)
239 {
240 int found = false;
241 for(unsigned int j = 0; j < mod_num; j++)
242 {
243 if(KviQString::equalCI(modes.at(idx), mod_tbl[j]))
244 {
245 mod = mod_cod[j];
246 found = true;
247 break;
248 }
249 }
250 if(found)
251 sum = sum | mod;
252 else
253 c->warning(__tr2qs_ctx("No such open mode '%Q'", "objects"), &modes.at(idx));
254 }
255 }
256 c->returnValue()->setBoolean(m_pFile->open(sum));
257 return true;
258 }
259
KVSO_CLASS_FUNCTION(file,isOpen)260 KVSO_CLASS_FUNCTION(file, isOpen)
261 {
262 CHECK_INTERNAL_POINTER(m_pFile)
263 c->returnValue()->setBoolean(m_pFile->isOpen());
264 return true;
265 }
266
KVSO_CLASS_FUNCTION(file,close)267 KVSO_CLASS_FUNCTION(file, close)
268 {
269 CHECK_INTERNAL_POINTER(m_pFile)
270 CHECK_FILE_IS_OPEN
271 m_pFile->close();
272 return true;
273 }
274
KVSO_CLASS_FUNCTION(file,flush)275 KVSO_CLASS_FUNCTION(file, flush)
276 {
277 CHECK_INTERNAL_POINTER(m_pFile)
278 CHECK_FILE_IS_OPEN
279 m_pFile->flush();
280 return true;
281 }
282
KVSO_CLASS_FUNCTION(file,size)283 KVSO_CLASS_FUNCTION(file, size)
284 {
285 CHECK_INTERNAL_POINTER(m_pFile)
286 c->returnValue()->setInteger((kvs_int_t)(m_pFile->size()));
287 return true;
288 }
289
KVSO_CLASS_FUNCTION(file,atEnd)290 KVSO_CLASS_FUNCTION(file, atEnd)
291 {
292 CHECK_INTERNAL_POINTER(m_pFile)
293 c->returnValue()->setInteger((kvs_int_t)(m_pFile->atEnd()));
294 return true;
295 }
296
KVSO_CLASS_FUNCTION(file,where)297 KVSO_CLASS_FUNCTION(file, where)
298 {
299 CHECK_INTERNAL_POINTER(m_pFile)
300 CHECK_FILE_IS_OPEN
301 c->returnValue()->setInteger((kvs_int_t)(m_pFile->pos()));
302 return true;
303 }
304
KVSO_CLASS_FUNCTION(file,seek)305 KVSO_CLASS_FUNCTION(file, seek)
306 {
307 CHECK_INTERNAL_POINTER(m_pFile)
308 kvs_uint_t uIndex;
309 KVSO_PARAMETERS_BEGIN(c)
310 KVSO_PARAMETER("index", KVS_PT_UNSIGNEDINTEGER, 0, uIndex)
311 KVSO_PARAMETERS_END(c)
312 CHECK_FILE_IS_OPEN
313 m_pFile->seek(uIndex);
314 return true;
315 }
316
KVSO_CLASS_FUNCTION(file,resize)317 KVSO_CLASS_FUNCTION(file, resize)
318 {
319 CHECK_INTERNAL_POINTER(m_pFile)
320 kvs_int_t iSize;
321 KVSO_PARAMETERS_BEGIN(c)
322 KVSO_PARAMETER("size", KVS_PT_INTEGER, 0, iSize)
323 KVSO_PARAMETERS_END(c)
324 CHECK_FILE_IS_OPEN
325 m_pFile->resize(iSize);
326 return true;
327 }
328
KVSO_CLASS_FUNCTION(file,putch)329 KVSO_CLASS_FUNCTION(file, putch)
330 {
331 CHECK_INTERNAL_POINTER(m_pFile)
332 QString szChar;
333 KVSO_PARAMETERS_BEGIN(c)
334 KVSO_PARAMETER("char", KVS_PT_STRING, 0, szChar)
335 KVSO_PARAMETERS_END(c)
336 if(szChar.length() > 1)
337 c->warning(__tr2qs_ctx("Argument too long, using only first char", "objects"));
338 QByteArray szCh = szChar.toUtf8();
339 if(!m_pFile->putChar(szCh[0]))
340 c->warning(__tr2qs_ctx("Write error occurred!", "objects"));
341 return true;
342 }
343
KVSO_CLASS_FUNCTION(file,getch)344 KVSO_CLASS_FUNCTION(file, getch)
345 {
346 CHECK_INTERNAL_POINTER(m_pFile)
347 CHECK_FILE_IS_OPEN
348 char ch;
349 if(!m_pFile->getChar(&ch))
350 c->warning(__tr2qs_ctx("Read error occurred!", "objects")); // c->error ?
351 QString szChar = QChar(ch);
352 c->returnValue()->setString(szChar);
353 return true;
354 }
355
KVSO_CLASS_FUNCTION(file,readByte)356 KVSO_CLASS_FUNCTION(file, readByte)
357 {
358 CHECK_INTERNAL_POINTER(m_pFile)
359 CHECK_FILE_IS_OPEN
360 char ch;
361 if(!m_pFile->getChar(&ch))
362 c->warning(__tr2qs_ctx("Read error occurred!", "objects")); // c->error ?
363
364 c->returnValue()->setInteger((kvs_int_t)ch);
365 return true;
366 }
367
KVSO_CLASS_FUNCTION(file,unGetch)368 KVSO_CLASS_FUNCTION(file, unGetch)
369 {
370 CHECK_INTERNAL_POINTER(m_pFile)
371 CHECK_FILE_IS_OPEN
372 QString szChar;
373 KVSO_PARAMETERS_BEGIN(c)
374 KVSO_PARAMETER("char", KVS_PT_STRING, 0, szChar)
375 KVSO_PARAMETERS_END(c)
376 if(szChar.length() > 1)
377 c->warning(__tr2qs_ctx("Argument too long, using only the first char", "objects"));
378 QByteArray szCh = szChar.toUtf8();
379 m_pFile->ungetChar(szCh[0]);
380 return true;
381 }
382
KVSO_CLASS_FUNCTION(file,readBlock)383 KVSO_CLASS_FUNCTION(file, readBlock)
384 {
385 CHECK_INTERNAL_POINTER(m_pFile)
386 CHECK_FILE_IS_OPEN
387 kvs_uint_t uLen;
388 KviKvsObject * pObject;
389 kvs_hobject_t hObject;
390 KVSO_PARAMETERS_BEGIN(c)
391 KVSO_PARAMETER("length", KVS_PT_UNSIGNEDINTEGER, 0, uLen)
392 KVSO_PARAMETER("hobject", KVS_PT_HOBJECT, KVS_PF_OPTIONAL, hObject)
393 KVSO_PARAMETERS_END(c)
394 if(uLen > (kvs_uint_t)m_pFile->size())
395 uLen = m_pFile->size();
396 if(hObject)
397 {
398 pObject = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
399 if(!pObject)
400 {
401 c->warning(__tr2qs_ctx("Buffer parameter is not an object", "objects"));
402 return true;
403 }
404 if(!pObject->inheritsClass("memorybuffer"))
405 {
406 c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object", "objects"));
407 return true;
408 }
409
410 ((KvsObject_memoryBuffer *)pObject)->pBuffer()->append(m_pFile->read(uLen));
411 return true;
412 }
413 else
414 {
415 char * buff = new char[uLen + 1];
416
417 int rlen = m_pFile->read(buff, uLen);
418 buff[rlen] = '\0';
419 QString szBlock(buff);
420 delete[] buff;
421 c->returnValue()->setString(szBlock);
422 }
423 return true;
424 }
425
KVSO_CLASS_FUNCTION(file,read)426 KVSO_CLASS_FUNCTION(file, read)
427 {
428 CHECK_INTERNAL_POINTER(m_pFile)
429 CHECK_FILE_IS_OPEN
430 QString szType;
431 KVSO_PARAMETERS_BEGIN(c)
432 KVSO_PARAMETER("type", KVS_PT_STRING, 0, szType)
433 KVSO_PARAMETERS_END(c)
434 if(KviQString::equalCI(szType, "String"))
435 {
436 QString szStr;
437 m_pFile->load(szStr);
438 c->returnValue()->setString(szStr);
439 }
440 else if(KviQString::equalCI(szType, "Integer"))
441 {
442 int iValue;
443 m_pFile->load(iValue);
444 c->returnValue()->setInteger(iValue);
445 }
446 else if(KviQString::equalCI(szType, "Array"))
447 {
448 QString szData;
449 m_pFile->load(szData);
450 KviKvsVariant * pVar = KviKvsVariant::unserialize(szData);
451 if(pVar->isArray())
452 c->returnValue()->setArray(pVar->array());
453 else
454 c->warning(__tr2qs_ctx("The incoming data is not an array", "objects"));
455 }
456 else if(KviQString::equalCI(szType, "Dict"))
457 {
458 QString szData;
459 m_pFile->load(szData);
460 KviKvsVariant * pVar = KviKvsVariant::unserialize(szData);
461 if(pVar->isHash())
462 c->returnValue()->setHash(pVar->hash());
463 else
464 c->warning(__tr2qs_ctx("The incoming data is not a dictionary", "objects"));
465 }
466 else if(KviQString::equalCI(szType, "String"))
467 {
468 QString szStr;
469 m_pFile->load(szStr);
470 c->returnValue()->setString(szStr);
471 }
472 else
473 {
474 c->warning(__tr2qs_ctx("Unsupported datatype '%Q'", "objects"), &szType);
475 }
476 return true;
477 }
478
KVSO_CLASS_FUNCTION(file,write)479 KVSO_CLASS_FUNCTION(file, write)
480 {
481 CHECK_INTERNAL_POINTER(m_pFile)
482 CHECK_FILE_IS_OPEN
483 KviKvsVariant * pVariantData;
484 KVSO_PARAMETERS_BEGIN(c)
485 KVSO_PARAMETER("variant_data", KVS_PT_VARIANT, 0, pVariantData)
486 KVSO_PARAMETERS_END(c)
487 if(pVariantData->isInteger())
488 {
489 kvs_int_t num;
490 pVariantData->asInteger(num);
491 m_pFile->save(num);
492 }
493 if(pVariantData->isHash() || pVariantData->isArray() || pVariantData->isString())
494 {
495 QString szTmp;
496 pVariantData->serialize(szTmp);
497 m_pFile->save(szTmp);
498 }
499 return true;
500 }
501
KVSO_CLASS_FUNCTION(file,writeBlock)502 KVSO_CLASS_FUNCTION(file, writeBlock)
503 {
504 CHECK_INTERNAL_POINTER(m_pFile)
505 kvs_uint_t uLen;
506 KviKvsObject * pObject;
507 KviKvsVariant * pVariantData;
508 kvs_hobject_t hObject;
509 KVSO_PARAMETERS_BEGIN(c)
510 KVSO_PARAMETER("string_or_hobject", KVS_PT_VARIANT, 0, pVariantData)
511 KVSO_PARAMETER("length", KVS_PT_UNSIGNEDINTEGER, KVS_PF_OPTIONAL, uLen)
512 KVSO_PARAMETERS_END(c)
513 if(!m_pFile->isOpen())
514 c->warning(__tr2qs_ctx("File is not open!", "objects"));
515 else
516 {
517 if(pVariantData->isHObject())
518 {
519 pVariantData->asHObject(hObject);
520 pObject = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
521 if(!pObject)
522 {
523 c->warning(__tr2qs_ctx("Buffer parameter is not an object", "objects"));
524 return true;
525 }
526 if(pObject->inheritsClass("memorybuffer"))
527 {
528 if(!uLen)
529 {
530 if(((KvsObject_memoryBuffer *)pObject)->pBuffer()->size())
531 uLen = ((KvsObject_memoryBuffer *)pObject)->pBuffer()->size();
532 else
533 {
534 c->warning(__tr2qs_ctx("The memoryBuffer object is empty: nothing will be saved", "objects"));
535 }
536 }
537 const char * pData = ((KvsObject_memoryBuffer *)pObject)->pBuffer()->data();
538 int rlen = m_pFile->write(pData, uLen);
539 c->returnValue()->setInteger(rlen);
540
541 }
542 else
543 {
544 c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object", "objects"));
545 return true;
546 }
547 }
548 else
549 {
550 if(!pVariantData->isString())
551 {
552 c->warning(__tr2qs_ctx("Block parameter must be a string or a memorybuffer object", "objects"));
553 return true;
554 }
555 QString szBlock;
556 pVariantData->asString(szBlock);
557 QByteArray block = szBlock.toUtf8();
558 int rlen = m_pFile->write(block.data(), uLen);
559 c->returnValue()->setInteger(rlen);
560 }
561 }
562 return true;
563 }
564
KVSO_CLASS_FUNCTION(file,readLine)565 KVSO_CLASS_FUNCTION(file, readLine)
566 {
567 CHECK_INTERNAL_POINTER(m_pFile)
568 CHECK_FILE_IS_OPEN
569 QString buffer;
570
571 buffer = m_pFile->readLine();
572 c->returnValue()->setString(buffer);
573 return true;
574 }
575
KVSO_CLASS_FUNCTION(file,writeLine)576 KVSO_CLASS_FUNCTION(file, writeLine)
577 {
578 CHECK_INTERNAL_POINTER(m_pFile)
579 CHECK_FILE_IS_OPEN
580 QString szLine;
581 KVSO_PARAMETERS_BEGIN(c)
582 KVSO_PARAMETER("text_line", KVS_PT_STRING, 0, szLine)
583 KVSO_PARAMETERS_END(c)
584 QTextStream ts(m_pFile);
585 ts << szLine;
586 return true;
587 }
588
KVSO_CLASS_FUNCTION(file,readHexBlock)589 KVSO_CLASS_FUNCTION(file, readHexBlock)
590 {
591 CHECK_INTERNAL_POINTER(m_pFile)
592 CHECK_FILE_IS_OPEN
593 kvs_uint_t uLen;
594 KVSO_PARAMETERS_BEGIN(c)
595 KVSO_PARAMETER("length", KVS_PT_UNSIGNEDINTEGER, 0, uLen)
596 KVSO_PARAMETERS_END(c)
597 if(uLen > (kvs_uint_t)m_pFile->size())
598 uLen = m_pFile->size();
599 char * buff = new char[uLen];
600 char * str = new char[(uLen * 2) + 1];
601 m_pFile->flush(); // advice from QFile man page (to avoid trash)
602 int rlen = m_pFile->read(buff, uLen);
603 int index = 0;
604 unsigned char byte, msb, lsb = 0;
605 for(int i = 0; i < rlen; i++)
606 {
607 byte = (unsigned char)buff[i];
608 lsb = byte & 0x0f;
609 msb = byte >> 4;
610 msb > 9 ? msb += '7' : msb += '0';
611 lsb > 9 ? lsb += '7' : lsb += '0';
612 str[index++] = msb;
613 str[index++] = lsb;
614 }
615 str[index] = '\0';
616 c->returnValue()->setString(str);
617 delete[] str;
618 delete[] buff;
619 return true;
620 }
621
KVSO_CLASS_FUNCTION(file,writeHexBlock)622 KVSO_CLASS_FUNCTION(file, writeHexBlock)
623 {
624 CHECK_INTERNAL_POINTER(m_pFile)
625 CHECK_FILE_IS_OPEN
626 QString szBlock;
627 kvs_uint_t uLen;
628 KVSO_PARAMETERS_BEGIN(c)
629 KVSO_PARAMETER("text_block", KVS_PT_STRING, 0, szBlock)
630 KVSO_PARAMETER("length", KVS_PT_UNSIGNEDINTEGER, KVS_PF_OPTIONAL, uLen)
631 KVSO_PARAMETERS_END(c)
632 if(szBlock.length() % 2)
633 {
634 c->warning(__tr2qs_ctx("Length of hex string is not multiple of 2", "objects"));
635 return true;
636 }
637 if(uLen > ((uint)szBlock.length() / 2) || !uLen)
638 uLen = szBlock.length();
639 else
640 uLen *= 2;
641 unsigned char byte, lsb, msb;
642 for(unsigned int i = 0; i < uLen; i += 2)
643 {
644 msb = szBlock.at(i).toLatin1();
645 lsb = szBlock.at(i + 1).toLatin1();
646
647 if(((msb >= 'A' && msb <= 'F') || (msb >= '0' && msb <= '9')) && ((lsb >= 'A' && lsb <= 'F') || (lsb >= '0' && lsb <= '9')))
648 {
649 msb >= 'A' ? msb -= '7' : msb -= '0';
650 lsb >= 'A' ? lsb -= '7' : lsb -= '0';
651 }
652 else
653 {
654 c->warning(__tr2qs_ctx("The hex string is not correct!", "objects"));
655 return true;
656 }
657 byte = (msb * 16) + lsb;
658 m_pFile->putChar(byte);
659 }
660 c->returnValue()->setInteger(uLen / 2);
661 return true;
662 }
663