Kstars

binfilehelper.h
1/*
2 SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#pragma once
8
9#include <QString>
10#include <QVector>
11
12#include <cstdio>
13
14class QString;
15
16/**
17 * @short A structure describing a data field in the binary file. Its size is 16 bytes.
18 */
19typedef struct dataElement
20{
21 char name[10] = ""; /**< Field name (eg. RA) */
22 qint8 size { 0 }; /**< Field size in bytes (eg. 4) */
23 quint8 type { 0 };
24 qint32 scale { 0 }; /**< Field scale. The final field value = raw_value * scale */
26
27/**
28 * @class BinFileHelper
29 *
30 * This class provides utility functions to handle binary data files in the format prescribed
31 * by KStars. The file format is designed specifically to support data that has the form of an
32 * array of structures. See data/README.fileformat for details.
33 * The methods use primitive C file I/O routines defined in stdio.h to obtain efficiency
34 * @short Implements an interface to handle binary data files used by KStars
35 * @author Akarsh Simha
36 * @version 1.0
37 */
39{
40 public:
41 /** Constructor */
43
44 /** Destructor */
46
47 /**
48 * @short Checks if a file exists. WARNING: Might be incompatible in other locales
49 */
50 static bool testFileExists(const QString &fileName);
51
52 /**
53 * WARNING: This function may not be compatible in other locales, because it calls QString::toAscii
54 * @short Open a Binary data file and set the handle
55 * @param fileName Reference to QString containing the name of the file
56 * @return Handle to the file if successful, nullptr if an error occurred, sets the error.
57 */
58
59 FILE *openFile(const QString &fileName);
60
61 /**
62 * @short Read the header and index table from the file and fill up the QVector s with the entries
63 * @return True if successful, false if an error occurred, sets the error.
64 */
65 bool readHeader();
66
67 /**
68 * @short Close the binary data file
69 */
70 void closeFile();
71
72 /**
73 * @short Get error number
74 * @return A number corresponding to the error
75 */
76 int getErrorNumber();
77
78 /**
79 * @short Get error string
80 * @return A QString containing the error message to be displayed
81 */
83
84 /**
85 * @short Get field by name
86 * @param fieldName Name of the field
87 * @return A dataElement structure containing field data if the field exists,
88 * containing junk values if the field doesn't exist
89 */
90 struct dataElement getField(const QString &fieldName) const;
91
92 /**
93 * @short Check whether a field exists
94 * @param FieldName Name of the field
95 * @return True if the field exists, false if it does not or the FD hasn't been read yet
96 */
97 bool isField(const QString &FieldName) const;
98
99 /**
100 * @short Check whether file properties are real or bogus
101 * @return The value of private variable indexUpdated, which is true if data has been updated
102 */
103 inline bool propertiesUpdated() const { return indexUpdated; }
104
105 /**
106 * @short Get the file handle corresponding to the currently open file
107 * @return The filehandle if a file is open, nullptr if no file is open
108 */
109 inline FILE *getFileHandle() const { return fileHandle; }
110
111 /**
112 * @short Returns the offset in the file corresponding to the given index ID
113 * @param id ID of the index entry whose offset is required
114 * @return The offset corresponding to that index ID, 0 if the index hasn't been read
115 */
116 inline long getOffset(int id) const { return (indexUpdated ? indexOffset.at(id) : 0); }
117
118 /**
119 * @short Returns the number of records under the given index ID
120 * @param id ID of the index entry
121 * @return The number of records under index that index ID, or 0 if the index has not been read
122 */
123 inline unsigned int getRecordCount(int id) const { return (indexUpdated ? indexCount.at(id) : 0); }
124
125 /**
126 * @short Returns the total number of records in the file
127 * @return The number of records in the file, or 0 if the index has not been read
128 */
129 inline unsigned long getRecordCount() const { return (indexUpdated ? recordCount : 0); }
130
131 /**
132 * @short Should we do byte swapping?
133 * @note To be called only after the header has been parsed
134 * @return true if we must do byte swapping, false if not
135 */
136 inline bool getByteSwap() const { return byteswap; }
137
138 /**
139 * @short Return a guessed record size
140 * @note The record size returned is guessed from the field descriptor table and may
141 * not be correct in many cases
142 * @return A guessed size of the record, or zero if the FD hasn't been read yet
143 */
144 inline int guessRecordSize() const { return (RSUpdated ? recordSize : 0); }
145
146 /**
147 * @short Override record size
148 * @note To be used to override the guess in case the guess is wrong. This method should be called
149 * before calling readHeader(). Use this only if you are sure of the recordSize or are sure
150 * that the guess will not work.
151 * @param rs The correct recordSize
152 */
153 inline void setRecordSize(int rs)
154 {
155 recordSize = rs;
156 RSUpdated = true;
157 }
158
159 /**
160 * @short Returns the number of fields as suggested by the field descriptor in the header
161 * @return Number of fields, or zero if the FD hasn't been read yet
162 */
163 inline int getFieldCount() const { return (FDUpdated ? nfields : 0); }
164
165 /**
166 * @short Returns the header text
167 * @return QString containing the header text if header has been read, blank QString otherwise
168 */
169 inline QString getHeaderText() const { return (preambleUpdated ? headerText : ""); }
170
171 /**
172 * @short Returns the offset at which the data begins
173 * @return The value of dataOffset if indexUpdated, else zero
174 */
175 inline long getDataOffset() const { return (indexUpdated ? dataOffset : 0); }
176
177 /**
178 * @short Returns the offset at which the index table begins
179 * @return The value of itableOffset if FDUpdated, else zero
180 */
181 inline long getIndexTableOffset() const { return (FDUpdated ? itableOffset : 0); }
182
183 /**
184 * @short Wrapper around fseek for large offsets
185 *
186 * fseek takes a signed long for the offset, since it can be
187 * either positive or negative. If the argument is a 32-bit
188 * unsigned integer, fseek will fail in most situations, since
189 * that will be interpreted as a number of the opposite sign.
190 * This wrapper circumvents that problem by repeatedly calling
191 * fseek twice if the offset is too large. Useful when 64-bit
192 * handling is really not necessary.
193 *
194 * @return Zero on success. Else, error code of the first failing fseek call.
195 * @note Clearly, this method can move forward only. When we need
196 * one that goes back, we'll implement that.
197 */
198 static int unsigned_KDE_fseek(FILE *stream, quint32 offset, int whence);
199
200 /*! @short An enum providing user-friendly names for errors encountered */
202 {
203 ERR_NULL, /*!< No error occurred */
204 ERR_FILEOPEN, /*!< File could not be opened */
205 ERR_FD_TRUNC, /*!< Field descriptor table is truncated */
206 ERR_INDEX_TRUNC, /*!< File ends prematurely, before expected end of index table */
207 ERR_INDEX_BADID, /*!< Index table has an invalid ID entry */
208 ERR_INDEX_IDMISMATCH, /*!< Index table has a mismatched ID entry [ID found in the wrong place] */
209 ERR_INDEX_BADOFFSET, /*!< Offset / Record count specified in the Index table is bad */
210 ERR_BADSEEK /*!< Premature end of file / bad seek while reading index table */
211 };
212
213 private:
214 /**
215 * @short Backends for readHeader without cleanup on abort
216 * @return Return the appropriate error code, or ERR_NULL if successful
217 */
218 enum Errors __readHeader();
219
220 /**
221 * @short Helper function that clears all field entries in the QVector fields
222 */
223 void clearFields();
224
225 /**
226 * @short Helper function that sets all variables to their initial values
227 */
228 void init();
229
230 /// Handle to the file.
231 FILE *fileHandle { nullptr};
232 /// Stores offsets corresponding to each index table entry
233 QVector<unsigned long> indexOffset;
234 /// Stores number of records under each index table entry
235 QVector<unsigned int> indexCount;
236 /// True if the data from the index, and associated properties have been updated
237 bool indexUpdated { false };
238 /// True if the data from the Field Descriptor, and associated properties have been updated
239 bool FDUpdated { false };
240 /// True if the recordSize parameter is set correctly, either manually or bye reading the FD
241 bool RSUpdated { false };
242 /// True if the data from the preamble and associated properties have been updated
243 bool preambleUpdated { false };
244 /// Stores the number corresponding to the previous error
245 enum Errors errnum { ERR_NULL };
246 /// True if byteswapping should be done
247 bool byteswap { false };
248 /// Stores the size of a record in bytes for quick retrieval
249 int recordSize { 0 };
250 /// Maintains a list of fields in the file, along with relevant details
252 /// Stores the file header text
253 QString headerText;
254 /// Stores the number of fields as indicated by the field descriptor
255 qint16 nfields { 0 };
256 /// Stores the size of the index table in number of entries
257 quint32 indexSize { 0 };
258 /// Stores the offset position of the first index table entry
259 long itableOffset { 0 };
260 /// Stores the offset position of the start of data
261 long dataOffset { 0 };
262 /// Stores the most recent 'unread' error message
263 QString errorMessage;
264 /// Stores the total number of records in the file
265 unsigned long recordCount { 0 };
266 /// Stores the version number of the file
267 quint8 versionNumber { 0 };
268};
This class provides utility functions to handle binary data files in the format prescribed by KStars.
static int unsigned_KDE_fseek(FILE *stream, quint32 offset, int whence)
Wrapper around fseek for large offsets.
struct dataElement getField(const QString &fieldName) const
Get field by name.
int getFieldCount() const
Returns the number of fields as suggested by the field descriptor in the header.
static bool testFileExists(const QString &fileName)
Checks if a file exists.
FILE * getFileHandle() const
Get the file handle corresponding to the currently open file.
long getDataOffset() const
Returns the offset at which the data begins.
void closeFile()
Close the binary data file.
bool readHeader()
Read the header and index table from the file and fill up the QVector s with the entries.
bool propertiesUpdated() const
Check whether file properties are real or bogus.
unsigned long getRecordCount() const
Returns the total number of records in the file.
int getErrorNumber()
Get error number.
BinFileHelper()
Constructor.
QString getHeaderText() const
Returns the header text.
bool getByteSwap() const
Should we do byte swapping?
unsigned int getRecordCount(int id) const
Returns the number of records under the given index ID.
~BinFileHelper()
Destructor.
long getOffset(int id) const
Returns the offset in the file corresponding to the given index ID.
Errors
An enum providing user-friendly names for errors encountered.
FILE * openFile(const QString &fileName)
WARNING: This function may not be compatible in other locales, because it calls QString::toAscii.
QString getError()
Get error string.
bool isField(const QString &FieldName) const
Check whether a field exists.
void setRecordSize(int rs)
Override record size.
long getIndexTableOffset() const
Returns the offset at which the index table begins.
int guessRecordSize() const
Return a guessed record size.
A structure describing a data field in the binary file.
char name[10]
Field name (eg.
qint8 size
Field size in bytes (eg.
qint32 scale
Field scale.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.