File: rtdelphi.h

package info (click to toggle)
robotour 3.1.1-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,596 kB
  • ctags: 2,972
  • sloc: cpp: 17,705; sh: 3,060; ansic: 2,778; makefile: 144
file content (191 lines) | stat: -rwxr-xr-x 6,635 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 * rtdelphi.h
 * 
 * Copyright (c) 2000-2004 by Florian Fischer (florianfischer@gmx.de)
 * and Martin Trautmann (martintrautmann@gmx.de) 
 * 
 * This file may be distributed and/or modified under the terms of the 
 * GNU General Public License version 2 as published by the Free Software 
 * Foundation. 
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * 
 */

/** \file 
  * Support for the Delphi binary file formats. 
  * They are quite a good format for saving binary data. 
  */

#ifndef __LRT_DELPHI_STREAMS__
#define __LRT_DELPHI_STREAMS__

#include "rtsystem.h"
#include "rtcollect.h"
#include "rtstring.h"
#include "rtstreams.h"

namespace lrt {

/** This data type can hold either a String, an integer or a floating-point
  * (double) value. It is much like a typesafe union of these types.
  */
class Variant {
public:
	/// The possible types this variable may have
	enum VariantType {
		typeString = 0,		///< The variant is currently a string.
		typeInt,			///< The variant is currently an integer.
		typeDouble			///< The variant is currently a double.
	};

	/// Creates a Variant which contains the integer 0.
	Variant();
	/// Copies the data over from the other variant.
	Variant(const Variant&);
	/// Copies the data over from the other variant.
	Variant& operator=(const Variant&);
	~Variant();

	/// Creates a Variant which contains the given integer.
	explicit Variant(int);
	/// Creates a Variant which contains the given double.
	explicit Variant(double);
	/// Creates a Variant which contains the given String.
	explicit Variant(const String&);

	/// Sets this variant's value to the given integer.
	void set(int);
	/// Sets this variant's value to the given double.
	void set(double);
	/// Sets this variant's value to the given String.
	void set(const String&);

	/** Extracts an integer from this variant. 
	  * Note that it is unimportant which type this variant actually contains,
	  * an integer will be generated from it.
	  * @param def (optional) The default value which is used if this variant
	  *            is currently a String and not interpretable as an integer.
	  */	  
	int getInt(int def = 0) const;

	/** Extracts a double from this variant. 
	  * Note that it is unimportant which type this variant actually contains,
	  * a double will be generated from it.
	  * @param def (optional) The default value which is used if this variant
	  *            is currently a String and not interpretable as a double.
	  */	  
	double getDouble(double def = 0.) const;

	/** Converts this variant's data to a String representation and returns 
	  * it. The operation does not change the variant itself.
	  */	  
	String getString() const;

	/** Returns the current type of this variant. 
	  */
	VariantType getCurrentType() const;

private:
	union {
		int i;
		double d;
		String* str;
	};
	VariantType curType;
};


/** Supports reading binary files in the Delphi format.
  * The advantage of the Delphi binary file format is that it has prefixes
  * which indicate the type of the next data structure in the file, so that
  * even if you don't know what's in the file, you can still properly parse it.
  * <p>
  * Even though the original Delphi format is Intel-centric, with little-endian
  * data format, this library should work on any platform.
  */
class DelphiDataInputStream : public FilterInputStream  
{
public:

	/** Creates a Delphi binary input stream which reads from another input stream.
	  * <b>Note:</b> When this input stream is deleted, the other one is deleted as well.
	  */
	DelphiDataInputStream(InputStream* in);
	/** Creates a Delphi binary input stream which reads from a file (given by its name). 
	  * This is a convenience constructor which ensures that the file is opened in binary
	  * mode.
	  */
	DelphiDataInputStream(const String& filename);

	virtual ~DelphiDataInputStream();
	
	/** Reads the next contained element from the file.
	  * If the next data in the file is not a known element, exits the app.
	  */
	Variant readAny();
	
	/** Reads a String from the file. 
	  * <b>Note:</b> If the next data in the file is not a Delphi string, exits the app. <br>
	  * <b>Note:</b> Supports short (<tt>0x06</tt>) and long (<tt>0x0C</tt>) strings. */
	String readString();
	/** Reads an integer from the file. 
	  * <b>Note:</b> If the next data in the file is not a Delphi integer, exits the app. <br>
	  * <b>Note:</b> Supports 8-bit, 16-bit and 32-bit integers. */
	int readInt();
	/** Reads a floating-point number from the file. 
	  * <b>Note:</b> If the next data in the file is not a Delphi floating-point, exits the app. <br>
	  * <b>Note:</b> Supports 80-bit Delphi floating point numbers. */
	double readDouble();
private:
	String doReadString(int type);
	int doReadInt(int type);
	double doReadDouble(int type);

	double ld2d(Array<unsigned char>&);
	void inverseByteOrder(unsigned char* data, int len);
};

/** Supports writing binary files in the Delphi format.
  * The advantage of the Delphi binary file format is that it has prefixes
  * which indicate the type of the next data structure in the file, so that
  * even if you don't know what's in the file, you can still properly parse it.
  * <p>
  * Even though the original Delphi format is Intel-centric, with little-endian
  * data format, this library should work on any platform.
  */
class DelphiDataOutputStream : public FilterOutputStream
{
public:
	/** Creates a Delphi binary output stream which writes to another input stream.
	  * <b>Note:</b> When this output stream is deleted, the other one is deleted as well.
	  */
	DelphiDataOutputStream(OutputStream* out);
	
	/** Writes another element to the stream. */
	bool writeAny(const Variant&);

	/** Writes a String to the stream. 
	  * <b>Note:</b> This implementation uses the short (<tt>0x06</tt>) and long (<tt>0x0C</tt>) strings. 
	  */
	bool writeString(const String&);

	/** Writes an integer to the stream. 
	  * <b>Note:</b> This implementation uses the 8-bit, 16-bit and 32-bit integer formats, 
	  * and always writes the smallest one which can hold the given number. 
	  */
	bool writeInt(int);

	/** Writes a double to the stream. 
	  */
	bool writeDouble(double);
private:
	void d2ld(double d, Array<unsigned char>& ld);
	void inverseByteOrder(unsigned char* data, int len);
	bool write4(int);
};

} // namespace

#endif