blob: 80f8a7967496e6978d27a1a0bb71b87116cda0ff [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19#include <rdr/HexInStream.h>
20#include <rdr/Exception.h>
21
22#include <stdlib.h>
23#include <ctype.h>
24
25using namespace rdr;
26
27const int DEFAULT_BUF_LEN = 16384;
28
29static inline int min(int a, int b) {return a<b ? a : b;}
30
31HexInStream::HexInStream(InStream& is, int bufSize_)
32: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
33{
34 ptr = end = start = new U8[bufSize];
35}
36
37HexInStream::~HexInStream() {
38 delete [] start;
39}
40
41
42bool HexInStream::readHexAndShift(char c, int* v) {
43 c=tolower(c);
44 if ((c >= '0') && (c <= '9'))
45 *v = (*v << 4) + (c - '0');
46 else if ((c >= 'a') && (c <= 'f'))
47 *v = (*v << 4) + (c - 'a' + 10);
48 else
49 return false;
50 return true;
51}
52
53bool HexInStream::hexStrToBin(const char* s, char** data, int* length) {
54 int l=strlen(s);
55 if ((l % 2) == 0) {
56 delete [] *data;
57 *data = 0; *length = 0;
58 if (l == 0)
59 return true;
60 *data = new char[l/2];
61 *length = l/2;
62 for(int i=0;i<l;i+=2) {
63 int byte = 0;
64 if (!readHexAndShift(s[i], &byte) ||
65 !readHexAndShift(s[i+1], &byte))
66 goto decodeError;
67 (*data)[i/2] = byte;
68 }
69 return true;
70 }
71decodeError:
72 delete [] *data;
73 *data = 0;
74 *length = 0;
75 return false;
76}
77
78
79int HexInStream::pos() {
80 return offset + ptr - start;
81}
82
83int HexInStream::overrun(int itemSize, int nItems, bool wait) {
84 if (itemSize > bufSize)
85 throw Exception("HexInStream overrun: max itemSize exceeded");
86
87 if (end - ptr != 0)
88 memmove(start, ptr, end - ptr);
89
90 end -= ptr - start;
91 offset += ptr - start;
92 ptr = start;
93
94 while (end < ptr + itemSize) {
95 int n = in_stream.check(2, 1, wait);
96 if (n == 0) return 0;
97 const U8* iptr = in_stream.getptr();
98 const U8* eptr = in_stream.getend();
99 int length = min((eptr - iptr)/2, start + bufSize - end);
100
101 U8* optr = (U8*) end;
102 for (int i=0; i<length; i++) {
103 int v = 0;
104 readHexAndShift(iptr[i*2], &v);
105 readHexAndShift(iptr[i*2+1], &v);
106 optr[i] = v;
107 }
108
109 in_stream.setptr(iptr + length*2);
110 end += length;
111 }
112
113 if (itemSize * nItems > end - ptr)
114 nItems = (end - ptr) / itemSize;
115
116 return nItems;
117}