1 /*
2     SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 /* NOTE: This file is a NON portable C file that need not be built for
8    KStars to be built.  This file is useful only to generate binary
9    data files and ensure that they comply with KStars' format, and
10    hence need not be cross platform.
11 
12    This file does not use Qt or KDE libraries as it is just provided
13    here as a tool to build and test data files for KStars
14 
15    Hence, we shall hide this file from the watchful eyes of Krazy
16 */
17 //krazy:skip
18 
19 #ifndef BINFILE_H
20 #define BINFILE_H
21 
22 #include <sys/types.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <math.h>
27 #include "byteorder.h"
28 
29 /* NOTE: HTM_LEVEL and other HTM-related stuff must be defined before using this header */
30 
31 // Bogus Define
32 #ifndef INDEX_ENTRY_SIZE
33 #define INDEX_ENTRY_SIZE 12
34 #endif
35 
36 /*
37  * enum listing out various possible data types
38  */
39 
40 enum dataType
41 {
42     DT_CHAR,   /* Character */
43     DT_INT8,   /* 8-bit Integer */
44     DT_UINT8,  /* 8-bit Unsigned Integer */
45     DT_INT16,  /* 16-bit Integer */
46     DT_UINT16, /* 16-bit Unsigned Integer */
47     DT_INT32,  /* 32-bit Integer */
48     DT_UINT32, /* 32-bit Unsigned Integer */
49     DT_CHARV,  /* Fixed-length array of characters */
50     DT_STR,    /* Variable length array of characters, either terminated by nullptr or by the limit on field size */
51     DT_SPCL =
52         128 /* Flag indicating that the field requires special treatment (eg: Different bits may mean different things) */
53 };
54 
55 /*
56  * struct to store the description of a field / data element in the binary files
57  */
58 
59 typedef struct dataElement
60 {
61     char name[10];
62     int8_t size;
63     u_int8_t type;
64     int32_t scale;
65 } dataElement;
66 
charv2str(char * str,char * charv,int n)67 void charv2str(char *str, char *charv, int n)
68 {
69     int i;
70     for (i = 0; i < n; ++i)
71     {
72         *str = *charv;
73         str++;
74         charv++;
75     }
76     *str = '\0';
77 }
78 
displayDataElementDescription(dataElement * e)79 int displayDataElementDescription(dataElement *e)
80 {
81     char str[11];
82     charv2str(str, e->name, 10);
83     printf("\nData Field:\n");
84     printf("  Name: %s\n", str);
85     printf("  Size: %d\n", e->size);
86     printf("  Type: %d\n", e->type);
87     printf("  Scale: %ld\n", e->scale);
88 }
89 
90 // NOTE: Ineffecient. Not to be used for high-productivity
91 // applications
swapbytes(char byteswap,void * ptr,int nbytes)92 void swapbytes(char byteswap, void *ptr, int nbytes)
93 {
94     char *destptr;
95     char *i;
96 
97     if (!byteswap)
98         return;
99 
100     destptr = (char *)malloc(nbytes);
101     i       = ((char *)ptr + (nbytes - 1));
102     while (i >= (char *)ptr)
103     {
104         *destptr = *i;
105         ++destptr;
106         --i;
107     }
108 
109     destptr -= nbytes;
110 
111     memcpy(ptr, (void *)destptr, nbytes);
112     free(destptr);
113 }
114 
trixel2number(char * trixel)115 u_int32_t trixel2number(char *trixel)
116 {
117     int index;
118     u_int32_t id = 0;
119     for (index = HTM_LEVEL + 1; index >= 1; --index)
120     {
121         id += (trixel[index] - '0') * (u_int16_t)round(pow(4, (HTM_LEVEL + 1 - index)));
122     }
123     id += ((trixel[0] == 'S') ? round(pow(4, HTM_LEVEL + 1)) + 1 : 0);
124     return id;
125 }
126 
number2trixel(char * trixel,u_int16_t number)127 char *number2trixel(char *trixel, u_int16_t number)
128 {
129     int index;
130     u_int16_t hpv = (u_int16_t)round(pow(4, HTM_LEVEL)) * 2;
131     if (number >= hpv)
132     {
133         trixel[0] = 'S';
134         number -= hpv;
135     }
136     else
137         trixel[0] = 'N';
138     hpv /= 2;
139 
140     for (index = 1; index < HTM_LEVEL + 2; ++index)
141     {
142         trixel[index] = (number - (number % hpv)) / hpv + '0';
143         number        = number % hpv;
144         hpv /= 4;
145     }
146 
147     trixel[HTM_LEVEL + 2] = '\0';
148 
149     return trixel;
150 }
151 
152 /*
153  * Convert a string to an int32_t with a double as an intermediate
154  * i : A pointer to the target int32_t
155  * str : A pointer to the string that carries the data
156  * ndec : Number of decimal places to truncate to
157  */
158 
str2int32(int32_t * i,const char * str,int ndec)159 int str2int32(int32_t *i, const char *str, int ndec)
160 {
161     double dbl;
162 
163     if (i == nullptr)
164         return 0;
165 
166     dbl = atof(str);
167 
168     *i = (int32_t)(round(dbl * pow(10, ndec)));
169 
170     return 1;
171 }
172 
173 /*
174  * Convert a string to an int16_t with a double as an intermediate
175  * i : A pointer to the target int16_t
176  * str : The string that carries the data
177  * ndec : Number of decimal places to truncate to
178  */
179 
str2int16(int16_t * i,const char * str,int ndec)180 int str2int16(int16_t *i, const char *str, int ndec)
181 {
182     double dbl;
183 
184     if (i == nullptr || str == nullptr)
185         return 0;
186 
187     dbl = atof(str);
188 
189     *i = (int16_t)(round(dbl * pow(10, ndec)));
190 
191     return 1;
192 }
193 
194 /*
195  * Convert a string into a character array for n characters
196  * a : The target array
197  * str : The string that carries the data
198  * n : Number of characters to convert
199  */
200 
str2charv(char * a,const char * str,int n)201 int str2charv(char *a, const char *str, int n)
202 {
203     if (a == nullptr || str == nullptr)
204         return 0;
205 
206     int ret = 1;
207 
208     for (int i = 0; i < n; ++i)
209     {
210         a[i] = ((ret < 0) ? '\0' : str[i]);
211         if (str[i] == '\0') /* We can do this safely because we aren't storing binary data in the DB */
212             ret = -1;
213     }
214     return ret;
215 }
216 
217 /*
218  * Check whether the string passed is blank
219  * str : String to check
220  * returns 1 if the string is blank, 0 otherwise.
221  */
222 
isblank(char * str)223 int isblank(char *str)
224 {
225     if (str == nullptr)
226         return 1;
227 
228     while (*str != '\0')
229     {
230         if (*str != ' ' && *str != '\n' && *str != '\r' && *str != '\t')
231             return 0;
232         ++str;
233     }
234     return 1;
235 }
236 
237 /*
238  * Write one data element description into a binary file header.
239  *
240  * f    : Handle of file to write into
241  * name : Name of the field, as a string. Max as specified in struct dataElement
242  * size : Size (in bytes) of the field
243  * type : Type of the field, as specified in enum dataType
244  * scale : Scale factor used for conversion of fixed-point reals to integers. N/A to DT_CHARV, DT_STR and DT_CHAR
245  */
246 
writeDataElementDescription(FILE * f,char * name,int8_t size,enum dataType type,int32_t scale)247 int writeDataElementDescription(FILE *f, char *name, int8_t size, enum dataType type, int32_t scale)
248 {
249     struct dataElement de;
250 
251     if (f == nullptr || name == nullptr)
252         return 0;
253 
254     str2charv(de.name, name, 10);
255     de.size  = size;
256     de.type  = type;
257     de.scale = scale;
258     fwrite(&de, sizeof(struct dataElement), 1, f);
259     return 1;
260 }
261 
writeIndexEntry(FILE * hf,u_int32_t trixel_id,u_int32_t offset,u_int32_t nrec)262 int writeIndexEntry(FILE *hf, u_int32_t trixel_id, u_int32_t offset, u_int32_t nrec)
263 {
264     if (hf == nullptr)
265         return 0;
266 
267     fwrite(&trixel_id, 4, 1, hf);
268     fwrite(&offset, 4, 1, hf);
269     fwrite(&nrec, 4, 1, hf);
270 
271     /* Put this just for safety, in case we change our mind - we should avoid screwing things up */
272     if (4 + 4 + 4 != INDEX_ENTRY_SIZE)
273     {
274         fprintf(stderr, "CODE ERROR: 4 + 4 + 4 != INDEX_ENTRY_SIZE\n");
275     }
276 
277     return 1;
278 }
279 
280 /*
281  * "Increments" a trixel
282  *
283  * str : String to hold the incremented trixel
284  */
285 /*
286 void nextTrixel(char *trixel) {
287 
288   char *ptr = trixel + HTM_LEVEL + 1;
289   while(ptr > trixel) {
290     *ptr = *ptr + 1;
291     if(*ptr != '4')
292       break;
293     *ptr = '0';
294     ptr--;
295   }
296   if(*ptr == 'N')
297     *ptr = 'S';
298   else if(*ptr == 'S')
299     *ptr = '0';
300 }
301 
302 */
303 #endif
304