1 /*
2
3 gg_endian.c -- Gaia functions for litte/big endian values handling
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43
44 */
45
46 #include <sys/types.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49
50 #if defined(_WIN32) && !defined(__MINGW32__)
51 #include "config-msvc.h"
52 #else
53 #include "config.h"
54 #endif
55
56 #include <spatialite/sqlite.h>
57
58 #include <spatialite/gaiageo.h>
59
60 GAIAGEO_DECLARE int
gaiaEndianArch()61 gaiaEndianArch ()
62 {
63 /* checking if target CPU is a little-endian one */
64 union cvt
65 {
66 unsigned char byte[4];
67 int int_value;
68 } convert;
69 convert.int_value = 1;
70 if (convert.byte[0] == 0)
71 return 0;
72 return 1;
73 }
74
75 GAIAGEO_DECLARE short
gaiaImport16(const unsigned char * p,int little_endian,int little_endian_arch)76 gaiaImport16 (const unsigned char *p, int little_endian, int little_endian_arch)
77 {
78 /* fetches a 16bit int from BLOB respecting declared endiannes */
79 union cvt
80 {
81 unsigned char byte[2];
82 short short_value;
83 } convert;
84 if (little_endian_arch)
85 {
86 /* Litte-Endian architecture [e.g. x86] */
87 if (!little_endian)
88 {
89 /* Big Endian data */
90 convert.byte[0] = *(p + 1);
91 convert.byte[1] = *(p + 0);
92 }
93 else
94 {
95 /* Little Endian data */
96 convert.byte[0] = *(p + 0);
97 convert.byte[1] = *(p + 1);
98 }
99 }
100 else
101 {
102 /* Big Endian architecture [e.g. PPC] */
103 if (!little_endian)
104 {
105 /* Big Endian data */
106 convert.byte[0] = *(p + 0);
107 convert.byte[1] = *(p + 1);
108 }
109 else
110 {
111 /* Little Endian data */
112 convert.byte[0] = *(p + 1);
113 convert.byte[1] = *(p + 0);
114 }
115 }
116 return convert.short_value;
117 }
118
119 GAIAGEO_DECLARE int
gaiaImport32(const unsigned char * p,int little_endian,int little_endian_arch)120 gaiaImport32 (const unsigned char *p, int little_endian, int little_endian_arch)
121 {
122 /* fetches a 32bit int from BLOB respecting declared endiannes */
123 union cvt
124 {
125 unsigned char byte[4];
126 int int_value;
127 } convert;
128 if (little_endian_arch)
129 {
130 /* Litte-Endian architecture [e.g. x86] */
131 if (!little_endian)
132 {
133 /* Big Endian data */
134 convert.byte[0] = *(p + 3);
135 convert.byte[1] = *(p + 2);
136 convert.byte[2] = *(p + 1);
137 convert.byte[3] = *(p + 0);
138 }
139 else
140 {
141 /* Little Endian data */
142 convert.byte[0] = *(p + 0);
143 convert.byte[1] = *(p + 1);
144 convert.byte[2] = *(p + 2);
145 convert.byte[3] = *(p + 3);
146 }
147 }
148 else
149 {
150 /* Big Endian architecture [e.g. PPC] */
151 if (!little_endian)
152 {
153 /* Big Endian data */
154 convert.byte[0] = *(p + 0);
155 convert.byte[1] = *(p + 1);
156 convert.byte[2] = *(p + 2);
157 convert.byte[3] = *(p + 3);
158 }
159 else
160 {
161 /* Little Endian data */
162 convert.byte[0] = *(p + 3);
163 convert.byte[1] = *(p + 2);
164 convert.byte[2] = *(p + 1);
165 convert.byte[3] = *(p + 0);
166 }
167 }
168 return convert.int_value;
169 }
170
171 GAIAGEO_DECLARE unsigned int
gaiaImportU32(const unsigned char * p,int little_endian,int little_endian_arch)172 gaiaImportU32 (const unsigned char *p, int little_endian,
173 int little_endian_arch)
174 {
175 /* fetches a 32bit uint from BLOB respecting declared endiannes */
176 union cvt
177 {
178 unsigned char byte[4];
179 unsigned int int_value;
180 } convert;
181 if (little_endian_arch)
182 {
183 /* Litte-Endian architecture [e.g. x86] */
184 if (!little_endian)
185 {
186 /* Big Endian data */
187 convert.byte[0] = *(p + 3);
188 convert.byte[1] = *(p + 2);
189 convert.byte[2] = *(p + 1);
190 convert.byte[3] = *(p + 0);
191 }
192 else
193 {
194 /* Little Endian data */
195 convert.byte[0] = *(p + 0);
196 convert.byte[1] = *(p + 1);
197 convert.byte[2] = *(p + 2);
198 convert.byte[3] = *(p + 3);
199 }
200 }
201 else
202 {
203 /* Big Endian architecture [e.g. PPC] */
204 if (!little_endian)
205 {
206 /* Big Endian data */
207 convert.byte[0] = *(p + 0);
208 convert.byte[1] = *(p + 1);
209 convert.byte[2] = *(p + 2);
210 convert.byte[3] = *(p + 3);
211 }
212 else
213 {
214 /* Little Endian data */
215 convert.byte[0] = *(p + 3);
216 convert.byte[1] = *(p + 2);
217 convert.byte[2] = *(p + 1);
218 convert.byte[3] = *(p + 0);
219 }
220 }
221 return convert.int_value;
222 }
223
224 GAIAGEO_DECLARE float
gaiaImportF32(const unsigned char * p,int little_endian,int little_endian_arch)225 gaiaImportF32 (const unsigned char *p, int little_endian,
226 int little_endian_arch)
227 {
228 /* fetches a 32bit float from BLOB respecting declared endiannes */
229 union cvt
230 {
231 unsigned char byte[4];
232 float flt_value;
233 } convert;
234 if (little_endian_arch)
235 {
236 /* Litte-Endian architecture [e.g. x86] */
237 if (!little_endian)
238 {
239 /* Big Endian data */
240 convert.byte[0] = *(p + 3);
241 convert.byte[1] = *(p + 2);
242 convert.byte[2] = *(p + 1);
243 convert.byte[3] = *(p + 0);
244 }
245 else
246 {
247 /* Little Endian data */
248 convert.byte[0] = *(p + 0);
249 convert.byte[1] = *(p + 1);
250 convert.byte[2] = *(p + 2);
251 convert.byte[3] = *(p + 3);
252 }
253 }
254 else
255 {
256 /* Big Endian architecture [e.g. PPC] */
257 if (!little_endian)
258 {
259 /* Big Endian data */
260 convert.byte[0] = *(p + 0);
261 convert.byte[1] = *(p + 1);
262 convert.byte[2] = *(p + 2);
263 convert.byte[3] = *(p + 3);
264 }
265 else
266 {
267 /* Little Endian data */
268 convert.byte[0] = *(p + 3);
269 convert.byte[1] = *(p + 2);
270 convert.byte[2] = *(p + 1);
271 convert.byte[3] = *(p + 0);
272 }
273 }
274 return convert.flt_value;
275 }
276
277 GAIAGEO_DECLARE double
gaiaImport64(const unsigned char * p,int little_endian,int little_endian_arch)278 gaiaImport64 (const unsigned char *p, int little_endian, int little_endian_arch)
279 {
280 /* fetches a 64bit double from BLOB respecting declared endiannes */
281 union cvt
282 {
283 unsigned char byte[8];
284 double double_value;
285 } convert;
286 if (little_endian_arch)
287 {
288 /* Litte-Endian architecture [e.g. x86] */
289 if (!little_endian)
290 {
291 /* Big Endian data */
292 convert.byte[0] = *(p + 7);
293 convert.byte[1] = *(p + 6);
294 convert.byte[2] = *(p + 5);
295 convert.byte[3] = *(p + 4);
296 convert.byte[4] = *(p + 3);
297 convert.byte[5] = *(p + 2);
298 convert.byte[6] = *(p + 1);
299 convert.byte[7] = *(p + 0);
300 }
301 else
302 {
303 /* Little Endian data */
304 convert.byte[0] = *(p + 0);
305 convert.byte[1] = *(p + 1);
306 convert.byte[2] = *(p + 2);
307 convert.byte[3] = *(p + 3);
308 convert.byte[4] = *(p + 4);
309 convert.byte[5] = *(p + 5);
310 convert.byte[6] = *(p + 6);
311 convert.byte[7] = *(p + 7);
312 }
313 }
314 else
315 {
316 /* Big Endian architecture [e.g. PPC] */
317 if (!little_endian)
318 {
319 /* Big Endian data */
320 convert.byte[0] = *(p + 0);
321 convert.byte[1] = *(p + 1);
322 convert.byte[2] = *(p + 2);
323 convert.byte[3] = *(p + 3);
324 convert.byte[4] = *(p + 4);
325 convert.byte[5] = *(p + 5);
326 convert.byte[6] = *(p + 6);
327 convert.byte[7] = *(p + 7);
328 }
329 else
330 {
331 /* Little Endian data */
332 convert.byte[0] = *(p + 7);
333 convert.byte[1] = *(p + 6);
334 convert.byte[2] = *(p + 5);
335 convert.byte[3] = *(p + 4);
336 convert.byte[4] = *(p + 3);
337 convert.byte[5] = *(p + 2);
338 convert.byte[6] = *(p + 1);
339 convert.byte[7] = *(p + 0);
340 }
341 }
342 return convert.double_value;
343 }
344
345 GAIAGEO_DECLARE sqlite3_int64
gaiaImportI64(const unsigned char * p,int little_endian,int little_endian_arch)346 gaiaImportI64 (const unsigned char *p, int little_endian,
347 int little_endian_arch)
348 {
349 /* fetches a 64bit INT from BLOB respecting declared endiannes */
350 union cvt
351 {
352 unsigned char byte[8];
353 sqlite3_int64 int64_value;
354 } convert;
355 if (little_endian_arch)
356 {
357 /* Litte-Endian architecture [e.g. x86] */
358 if (!little_endian)
359 {
360 /* Big Endian data */
361 convert.byte[0] = *(p + 7);
362 convert.byte[1] = *(p + 6);
363 convert.byte[2] = *(p + 5);
364 convert.byte[3] = *(p + 4);
365 convert.byte[4] = *(p + 3);
366 convert.byte[5] = *(p + 2);
367 convert.byte[6] = *(p + 1);
368 convert.byte[7] = *(p + 0);
369 }
370 else
371 {
372 /* Little Endian data */
373 convert.byte[0] = *(p + 0);
374 convert.byte[1] = *(p + 1);
375 convert.byte[2] = *(p + 2);
376 convert.byte[3] = *(p + 3);
377 convert.byte[4] = *(p + 4);
378 convert.byte[5] = *(p + 5);
379 convert.byte[6] = *(p + 6);
380 convert.byte[7] = *(p + 7);
381 }
382 }
383 else
384 {
385 /* Big Endian architecture [e.g. PPC] */
386 if (!little_endian)
387 {
388 /* Big Endian data */
389 convert.byte[0] = *(p + 0);
390 convert.byte[1] = *(p + 1);
391 convert.byte[2] = *(p + 2);
392 convert.byte[3] = *(p + 3);
393 convert.byte[4] = *(p + 4);
394 convert.byte[5] = *(p + 5);
395 convert.byte[6] = *(p + 6);
396 convert.byte[7] = *(p + 7);
397 }
398 else
399 {
400 /* Little Endian data */
401 convert.byte[0] = *(p + 7);
402 convert.byte[1] = *(p + 6);
403 convert.byte[2] = *(p + 5);
404 convert.byte[3] = *(p + 4);
405 convert.byte[4] = *(p + 3);
406 convert.byte[5] = *(p + 2);
407 convert.byte[6] = *(p + 1);
408 convert.byte[7] = *(p + 0);
409 }
410 }
411 return convert.int64_value;
412 }
413
414 GAIAGEO_DECLARE void
gaiaExport16(unsigned char * p,short value,int little_endian,int little_endian_arch)415 gaiaExport16 (unsigned char *p, short value, int little_endian,
416 int little_endian_arch)
417 {
418 /* stores a 16bit int into a BLOB respecting declared endiannes */
419 union cvt
420 {
421 unsigned char byte[2];
422 short short_value;
423 } convert;
424 convert.short_value = value;
425 if (little_endian_arch)
426 {
427 /* Litte-Endian architecture [e.g. x86] */
428 if (!little_endian)
429 {
430 /* Big Endian data */
431 *(p + 1) = convert.byte[1];
432 *(p + 0) = convert.byte[0];
433 }
434 else
435 {
436 /* Little Endian data */
437 *(p + 0) = convert.byte[0];
438 *(p + 1) = convert.byte[1];
439 }
440 }
441 else
442 {
443 /* Big Endian architecture [e.g. PPC] */
444 if (!little_endian)
445 {
446 /* Big Endian data */
447 *(p + 0) = convert.byte[0];
448 *(p + 1) = convert.byte[1];
449 }
450 else
451 {
452 /* Little Endian data */
453 *(p + 1) = convert.byte[0];
454 *(p + 0) = convert.byte[1];
455 }
456 }
457 }
458
459 GAIAGEO_DECLARE void
gaiaExport32(unsigned char * p,int value,int little_endian,int little_endian_arch)460 gaiaExport32 (unsigned char *p, int value, int little_endian,
461 int little_endian_arch)
462 {
463 /* stores a 32bit int into a BLOB respecting declared endiannes */
464 union cvt
465 {
466 unsigned char byte[4];
467 int int_value;
468 } convert;
469 convert.int_value = value;
470 if (little_endian_arch)
471 {
472 /* Litte-Endian architecture [e.g. x86] */
473 if (!little_endian)
474 {
475 /* Big Endian data */
476 *(p + 3) = convert.byte[0];
477 *(p + 2) = convert.byte[1];
478 *(p + 1) = convert.byte[2];
479 *(p + 0) = convert.byte[3];
480 }
481 else
482 {
483 /* Little Endian data */
484 *(p + 0) = convert.byte[0];
485 *(p + 1) = convert.byte[1];
486 *(p + 2) = convert.byte[2];
487 *(p + 3) = convert.byte[3];
488 }
489 }
490 else
491 {
492 /* Big Endian architecture [e.g. PPC] */
493 if (!little_endian)
494 {
495 /* Big Endian data */
496 *(p + 0) = convert.byte[0];
497 *(p + 1) = convert.byte[1];
498 *(p + 2) = convert.byte[2];
499 *(p + 3) = convert.byte[3];
500 }
501 else
502 {
503 /* Little Endian data */
504 *(p + 3) = convert.byte[0];
505 *(p + 2) = convert.byte[1];
506 *(p + 1) = convert.byte[2];
507 *(p + 0) = convert.byte[3];
508 }
509 }
510 }
511
512 GAIAGEO_DECLARE void
gaiaExportU32(unsigned char * p,unsigned int value,int little_endian,int little_endian_arch)513 gaiaExportU32 (unsigned char *p, unsigned int value, int little_endian,
514 int little_endian_arch)
515 {
516 /* stores a 32bit int into a BLOB respecting declared endiannes */
517 union cvt
518 {
519 unsigned char byte[4];
520 unsigned int int_value;
521 } convert;
522 convert.int_value = value;
523 if (little_endian_arch)
524 {
525 /* Litte-Endian architecture [e.g. x86] */
526 if (!little_endian)
527 {
528 /* Big Endian data */
529 *(p + 3) = convert.byte[0];
530 *(p + 2) = convert.byte[1];
531 *(p + 1) = convert.byte[2];
532 *(p + 0) = convert.byte[3];
533 }
534 else
535 {
536 /* Little Endian data */
537 *(p + 0) = convert.byte[0];
538 *(p + 1) = convert.byte[1];
539 *(p + 2) = convert.byte[2];
540 *(p + 3) = convert.byte[3];
541 }
542 }
543 else
544 {
545 /* Big Endian architecture [e.g. PPC] */
546 if (!little_endian)
547 {
548 /* Big Endian data */
549 *(p + 0) = convert.byte[0];
550 *(p + 1) = convert.byte[1];
551 *(p + 2) = convert.byte[2];
552 *(p + 3) = convert.byte[3];
553 }
554 else
555 {
556 /* Little Endian data */
557 *(p + 3) = convert.byte[0];
558 *(p + 2) = convert.byte[1];
559 *(p + 1) = convert.byte[2];
560 *(p + 0) = convert.byte[3];
561 }
562 }
563 }
564
565 GAIAGEO_DECLARE void
gaiaExportF32(unsigned char * p,float value,int little_endian,int little_endian_arch)566 gaiaExportF32 (unsigned char *p, float value, int little_endian,
567 int little_endian_arch)
568 {
569 /* stores a 32bit float into a BLOB respecting declared endiannes */
570 union cvt
571 {
572 unsigned char byte[4];
573 float flt_value;
574 } convert;
575 convert.flt_value = value;
576 if (little_endian_arch)
577 {
578 /* Litte-Endian architecture [e.g. x86] */
579 if (!little_endian)
580 {
581 /* Big Endian data */
582 *(p + 3) = convert.byte[0];
583 *(p + 2) = convert.byte[1];
584 *(p + 1) = convert.byte[2];
585 *(p + 0) = convert.byte[3];
586 }
587 else
588 {
589 /* Little Endian data */
590 *(p + 0) = convert.byte[0];
591 *(p + 1) = convert.byte[1];
592 *(p + 2) = convert.byte[2];
593 *(p + 3) = convert.byte[3];
594 }
595 }
596 else
597 {
598 /* Big Endian architecture [e.g. PPC] */
599 if (!little_endian)
600 {
601 /* Big Endian data */
602 *(p + 0) = convert.byte[0];
603 *(p + 1) = convert.byte[1];
604 *(p + 2) = convert.byte[2];
605 *(p + 3) = convert.byte[3];
606 }
607 else
608 {
609 /* Little Endian data */
610 *(p + 3) = convert.byte[0];
611 *(p + 2) = convert.byte[1];
612 *(p + 1) = convert.byte[2];
613 *(p + 0) = convert.byte[3];
614 }
615 }
616 }
617
618 GAIAGEO_DECLARE void
gaiaExport64(unsigned char * p,double value,int little_endian,int little_endian_arch)619 gaiaExport64 (unsigned char *p, double value, int little_endian,
620 int little_endian_arch)
621 {
622 /* stores a 64bit double into a BLOB respecting declared endiannes */
623 union cvt
624 {
625 unsigned char byte[8];
626 double double_value;
627 } convert;
628 convert.double_value = value;
629 if (little_endian_arch)
630 {
631 /* Litte-Endian architecture [e.g. x86] */
632 if (!little_endian)
633 {
634 /* Big Endian data */
635 *(p + 7) = convert.byte[0];
636 *(p + 6) = convert.byte[1];
637 *(p + 5) = convert.byte[2];
638 *(p + 4) = convert.byte[3];
639 *(p + 3) = convert.byte[4];
640 *(p + 2) = convert.byte[5];
641 *(p + 1) = convert.byte[6];
642 *(p + 0) = convert.byte[7];
643 }
644 else
645 {
646 /* Little Endian data */
647 *(p + 0) = convert.byte[0];
648 *(p + 1) = convert.byte[1];
649 *(p + 2) = convert.byte[2];
650 *(p + 3) = convert.byte[3];
651 *(p + 4) = convert.byte[4];
652 *(p + 5) = convert.byte[5];
653 *(p + 6) = convert.byte[6];
654 *(p + 7) = convert.byte[7];
655 }
656 }
657 else
658 {
659 /* Big Endian architecture [e.g. PPC] */
660 if (!little_endian)
661 {
662 /* Big Endian data */
663 *(p + 0) = convert.byte[0];
664 *(p + 1) = convert.byte[1];
665 *(p + 2) = convert.byte[2];
666 *(p + 3) = convert.byte[3];
667 *(p + 4) = convert.byte[4];
668 *(p + 5) = convert.byte[5];
669 *(p + 6) = convert.byte[6];
670 *(p + 7) = convert.byte[7];
671 }
672 else
673 {
674 /* Little Endian data */
675 *(p + 7) = convert.byte[0];
676 *(p + 6) = convert.byte[1];
677 *(p + 5) = convert.byte[2];
678 *(p + 4) = convert.byte[3];
679 *(p + 3) = convert.byte[4];
680 *(p + 2) = convert.byte[5];
681 *(p + 1) = convert.byte[6];
682 *(p + 0) = convert.byte[7];
683 }
684 }
685 }
686
687 GAIAGEO_DECLARE void
gaiaExportI64(unsigned char * p,sqlite3_int64 value,int little_endian,int little_endian_arch)688 gaiaExportI64 (unsigned char *p, sqlite3_int64 value, int little_endian,
689 int little_endian_arch)
690 {
691 /* stores a 64bit INT into a BLOB respecting declared endiannes */
692 union cvt
693 {
694 unsigned char byte[8];
695 sqlite3_int64 int64_value;
696 } convert;
697 convert.int64_value = value;
698 if (little_endian_arch)
699 {
700 /* Litte-Endian architecture [e.g. x86] */
701 if (!little_endian)
702 {
703 /* Big Endian data */
704 *(p + 7) = convert.byte[0];
705 *(p + 6) = convert.byte[1];
706 *(p + 5) = convert.byte[2];
707 *(p + 4) = convert.byte[3];
708 *(p + 3) = convert.byte[4];
709 *(p + 2) = convert.byte[5];
710 *(p + 1) = convert.byte[6];
711 *(p + 0) = convert.byte[7];
712 }
713 else
714 {
715 /* Little Endian data */
716 *(p + 0) = convert.byte[0];
717 *(p + 1) = convert.byte[1];
718 *(p + 2) = convert.byte[2];
719 *(p + 3) = convert.byte[3];
720 *(p + 4) = convert.byte[4];
721 *(p + 5) = convert.byte[5];
722 *(p + 6) = convert.byte[6];
723 *(p + 7) = convert.byte[7];
724 }
725 }
726 else
727 {
728 /* Big Endian architecture [e.g. PPC] */
729 if (!little_endian)
730 {
731 /* Big Endian data */
732 *(p + 0) = convert.byte[0];
733 *(p + 1) = convert.byte[1];
734 *(p + 2) = convert.byte[2];
735 *(p + 3) = convert.byte[3];
736 *(p + 4) = convert.byte[4];
737 *(p + 5) = convert.byte[5];
738 *(p + 6) = convert.byte[6];
739 *(p + 7) = convert.byte[7];
740 }
741 else
742 {
743 /* Little Endian data */
744 *(p + 7) = convert.byte[0];
745 *(p + 6) = convert.byte[1];
746 *(p + 5) = convert.byte[2];
747 *(p + 4) = convert.byte[3];
748 *(p + 3) = convert.byte[4];
749 *(p + 2) = convert.byte[5];
750 *(p + 1) = convert.byte[6];
751 *(p + 0) = convert.byte[7];
752 }
753 }
754 }
755