File indexing completed on 2024-04-28 03:42:51

0001 /*
0002     SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /* NOTE: This file is a NON portable C file that need not be built for
0008    KStars to be built.  This file is useful only to generate binary
0009    data files and ensure that they comply with KStars' format, and
0010    hence need not be cross platform.
0011 
0012    This file does not use Qt or KDE libraries as it is just provided
0013    here as a tool to build and test data files for KStars
0014 
0015    Hence, we shall hide this file from the watchful eyes of Krazy
0016 */
0017 //krazy:skip
0018 
0019 #ifndef BINFILE_H
0020 #define BINFILE_H
0021 
0022 #include <sys/types.h>
0023 #include <string.h>
0024 #include <stdlib.h>
0025 #include <stdio.h>
0026 #include <math.h>
0027 #include "byteorder.h"
0028 
0029 /* NOTE: HTM_LEVEL and other HTM-related stuff must be defined before using this header */
0030 
0031 // Bogus Define
0032 #ifndef INDEX_ENTRY_SIZE
0033 #define INDEX_ENTRY_SIZE 12
0034 #endif
0035 
0036 /*
0037  * enum listing out various possible data types
0038  */
0039 
0040 enum dataType
0041 {
0042     DT_CHAR,   /* Character */
0043     DT_INT8,   /* 8-bit Integer */
0044     DT_UINT8,  /* 8-bit Unsigned Integer */
0045     DT_INT16,  /* 16-bit Integer */
0046     DT_UINT16, /* 16-bit Unsigned Integer */
0047     DT_INT32,  /* 32-bit Integer */
0048     DT_UINT32, /* 32-bit Unsigned Integer */
0049     DT_CHARV,  /* Fixed-length array of characters */
0050     DT_STR,    /* Variable length array of characters, either terminated by nullptr or by the limit on field size */
0051     DT_SPCL =
0052         128 /* Flag indicating that the field requires special treatment (eg: Different bits may mean different things) */
0053 };
0054 
0055 /*
0056  * struct to store the description of a field / data element in the binary files
0057  */
0058 
0059 typedef struct dataElement
0060 {
0061     char name[10];
0062     int8_t size;
0063     u_int8_t type;
0064     int32_t scale;
0065 } dataElement;
0066 
0067 void charv2str(char *str, char *charv, int n)
0068 {
0069     int i;
0070     for (i = 0; i < n; ++i)
0071     {
0072         *str = *charv;
0073         str++;
0074         charv++;
0075     }
0076     *str = '\0';
0077 }
0078 
0079 int displayDataElementDescription(dataElement *e)
0080 {
0081     char str[11];
0082     charv2str(str, e->name, 10);
0083     printf("\nData Field:\n");
0084     printf("  Name: %s\n", str);
0085     printf("  Size: %d\n", e->size);
0086     printf("  Type: %d\n", e->type);
0087     printf("  Scale: %ld\n", e->scale);
0088 }
0089 
0090 // NOTE: Ineffecient. Not to be used for high-productivity
0091 // applications
0092 void swapbytes(char byteswap, void *ptr, int nbytes)
0093 {
0094     char *destptr;
0095     char *i;
0096 
0097     if (!byteswap)
0098         return;
0099 
0100     destptr = (char *)malloc(nbytes);
0101     i       = ((char *)ptr + (nbytes - 1));
0102     while (i >= (char *)ptr)
0103     {
0104         *destptr = *i;
0105         ++destptr;
0106         --i;
0107     }
0108 
0109     destptr -= nbytes;
0110 
0111     memcpy(ptr, (void *)destptr, nbytes);
0112     free(destptr);
0113 }
0114 
0115 u_int32_t trixel2number(char *trixel)
0116 {
0117     int index;
0118     u_int32_t id = 0;
0119     for (index = HTM_LEVEL + 1; index >= 1; --index)
0120     {
0121         id += (trixel[index] - '0') * (u_int16_t)round(pow(4, (HTM_LEVEL + 1 - index)));
0122     }
0123     id += ((trixel[0] == 'S') ? round(pow(4, HTM_LEVEL + 1)) + 1 : 0);
0124     return id;
0125 }
0126 
0127 char *number2trixel(char *trixel, u_int16_t number)
0128 {
0129     int index;
0130     u_int16_t hpv = (u_int16_t)round(pow(4, HTM_LEVEL)) * 2;
0131     if (number >= hpv)
0132     {
0133         trixel[0] = 'S';
0134         number -= hpv;
0135     }
0136     else
0137         trixel[0] = 'N';
0138     hpv /= 2;
0139 
0140     for (index = 1; index < HTM_LEVEL + 2; ++index)
0141     {
0142         trixel[index] = (number - (number % hpv)) / hpv + '0';
0143         number        = number % hpv;
0144         hpv /= 4;
0145     }
0146 
0147     trixel[HTM_LEVEL + 2] = '\0';
0148 
0149     return trixel;
0150 }
0151 
0152 /*
0153  * Convert a string to an int32_t with a double as an intermediate
0154  * i : A pointer to the target int32_t
0155  * str : A pointer to the string that carries the data
0156  * ndec : Number of decimal places to truncate to
0157  */
0158 
0159 int str2int32(int32_t *i, const char *str, int ndec)
0160 {
0161     double dbl;
0162 
0163     if (i == nullptr)
0164         return 0;
0165 
0166     dbl = atof(str);
0167 
0168     *i = (int32_t)(round(dbl * pow(10, ndec)));
0169 
0170     return 1;
0171 }
0172 
0173 /*
0174  * Convert a string to an int16_t with a double as an intermediate
0175  * i : A pointer to the target int16_t
0176  * str : The string that carries the data
0177  * ndec : Number of decimal places to truncate to
0178  */
0179 
0180 int str2int16(int16_t *i, const char *str, int ndec)
0181 {
0182     double dbl;
0183 
0184     if (i == nullptr || str == nullptr)
0185         return 0;
0186 
0187     dbl = atof(str);
0188 
0189     *i = (int16_t)(round(dbl * pow(10, ndec)));
0190 
0191     return 1;
0192 }
0193 
0194 /*
0195  * Convert a string into a character array for n characters
0196  * a : The target array
0197  * str : The string that carries the data
0198  * n : Number of characters to convert
0199  */
0200 
0201 int str2charv(char *a, const char *str, int n)
0202 {
0203     if (a == nullptr || str == nullptr)
0204         return 0;
0205 
0206     int ret = 1;
0207 
0208     for (int i = 0; i < n; ++i)
0209     {
0210         a[i] = ((ret < 0) ? '\0' : str[i]);
0211         if (str[i] == '\0') /* We can do this safely because we aren't storing binary data in the DB */
0212             ret = -1;
0213     }
0214     return ret;
0215 }
0216 
0217 /*
0218  * Check whether the string passed is blank
0219  * str : String to check
0220  * returns 1 if the string is blank, 0 otherwise.
0221  */
0222 
0223 int isblank(char *str)
0224 {
0225     if (str == nullptr)
0226         return 1;
0227 
0228     while (*str != '\0')
0229     {
0230         if (*str != ' ' && *str != '\n' && *str != '\r' && *str != '\t')
0231             return 0;
0232         ++str;
0233     }
0234     return 1;
0235 }
0236 
0237 /*
0238  * Write one data element description into a binary file header.
0239  *
0240  * f    : Handle of file to write into
0241  * name : Name of the field, as a string. Max as specified in struct dataElement
0242  * size : Size (in bytes) of the field
0243  * type : Type of the field, as specified in enum dataType
0244  * scale : Scale factor used for conversion of fixed-point reals to integers. N/A to DT_CHARV, DT_STR and DT_CHAR
0245  */
0246 
0247 int writeDataElementDescription(FILE *f, char *name, int8_t size, enum dataType type, int32_t scale)
0248 {
0249     struct dataElement de;
0250 
0251     if (f == nullptr || name == nullptr)
0252         return 0;
0253 
0254     str2charv(de.name, name, 10);
0255     de.size  = size;
0256     de.type  = type;
0257     de.scale = scale;
0258     fwrite(&de, sizeof(struct dataElement), 1, f);
0259     return 1;
0260 }
0261 
0262 int writeIndexEntry(FILE *hf, u_int32_t trixel_id, u_int32_t offset, u_int32_t nrec)
0263 {
0264     if (hf == nullptr)
0265         return 0;
0266 
0267     fwrite(&trixel_id, 4, 1, hf);
0268     fwrite(&offset, 4, 1, hf);
0269     fwrite(&nrec, 4, 1, hf);
0270 
0271     /* Put this just for safety, in case we change our mind - we should avoid screwing things up */
0272     if (4 + 4 + 4 != INDEX_ENTRY_SIZE)
0273     {
0274         fprintf(stderr, "CODE ERROR: 4 + 4 + 4 != INDEX_ENTRY_SIZE\n");
0275     }
0276 
0277     return 1;
0278 }
0279 
0280 /*
0281  * "Increments" a trixel
0282  *
0283  * str : String to hold the incremented trixel
0284  */
0285 /*
0286 void nextTrixel(char *trixel) {
0287 
0288   char *ptr = trixel + HTM_LEVEL + 1;
0289   while(ptr > trixel) {
0290     *ptr = *ptr + 1;
0291     if(*ptr != '4')
0292       break;
0293     *ptr = '0';
0294     ptr--;
0295   }
0296   if(*ptr == 'N')
0297     *ptr = 'S';
0298   else if(*ptr == 'S')
0299     *ptr = '0';
0300 }
0301 
0302 */
0303 #endif