Kstars

binfilehelper.h
1 /*
2  SPDX-FileCopyrightText: 2008 Akarsh Simha <[email protected]>
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 
14 class QString;
15 
16 /**
17  * @short A structure describing a data field in the binary file. Its size is 16 bytes.
18  */
19 typedef 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 */
25 } dataElement;
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 */
42  BinFileHelper();
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  */
82  QString getError();
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 */
201  enum Errors
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
251  QVector<dataElement *> fields;
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 };
int guessRecordSize() const
Return a guessed record size.
static int unsigned_KDE_fseek(FILE *stream, quint32 offset, int whence)
Wrapper around fseek for large offsets.
bool propertiesUpdated() const
Check whether file properties are real or bogus.
FILE * getFileHandle() const
Get the file handle corresponding to the currently open file.
static bool testFileExists(const QString &fileName)
Checks if a file exists.
bool readHeader()
Read the header and index table from the file and fill up the QVector s with the entries.
int getFieldCount() const
Returns the number of fields as suggested by the field descriptor in the header.
bool getByteSwap() const
Should we do byte swapping?
~BinFileHelper()
Destructor.
void setRecordSize(int rs)
Override record size.
bool isField(const QString &FieldName) const
Check whether a field exists.
void closeFile()
Close the binary data file.
unsigned int getRecordCount(int id) const
Returns the number of records under the given index ID.
QString getError()
Get error string.
const T & at(int i) const const
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.
struct dataElement getField(const QString &fieldName) const
Get field by name.
Implements an interface to handle binary data files used by KStars.
Definition: binfilehelper.h:38
char name[10]
Field name (eg.
Definition: binfilehelper.h:21
unsigned long getRecordCount() const
Returns the total number of records in the file.
qint8 size
Field size in bytes (eg.
Definition: binfilehelper.h:22
A structure describing a data field in the binary file.
Definition: binfilehelper.h:19
long getIndexTableOffset() const
Returns the offset at which the index table begins.
BinFileHelper()
Constructor.
qint32 scale
Field scale.
Definition: binfilehelper.h:24
FILE * openFile(const QString &fileName)
WARNING: This function may not be compatible in other locales, because it calls QString::toAscii.
long getDataOffset() const
Returns the offset at which the data begins.
int getErrorNumber()
Get error number.
QString getHeaderText() const
Returns the header text.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Oct 1 2023 04:02:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.