Line data Source code
1 : /*
2 : * libpino - endianness.c
3 : *
4 : * This file is part of libpino.
5 : *
6 : * Author: Go Kudo <zeriyoshi@gmail.com>
7 : * SPDX-License-Identifier: MIT
8 : */
9 :
10 : #include <pino/endianness.h>
11 : #include <pino/portable.h>
12 :
13 : #include "internal/bswap.h"
14 : #include "internal/common.h"
15 :
16 : #define ENDIANNESS_UNKNOWN 0
17 : #define ENDIANNESS_LITTLE 1
18 : #define ENDIANNESS_BIG 2
19 :
20 : #define bswap_memcpy pino_bswap_memcpy
21 :
22 : #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
23 : static uint8_t g_endianness = ENDIANNESS_LITTLE;
24 : #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
25 : static uint8_t g_endianness = ENDIANNESS_BIG;
26 : #else
27 : static uint8_t g_endianness = ENDIANNESS_UNKNOWN;
28 : #endif
29 :
30 3095 : static inline uint8_t platform_endianness(void)
31 : {
32 3095 : uint32_t i = 1;
33 3095 : uint8_t *p = (uint8_t *)&i;
34 :
35 3095 : if (g_endianness != ENDIANNESS_UNKNOWN) {
36 3095 : return g_endianness;
37 : }
38 :
39 0 : return g_endianness = (p[0] == 1) ? ENDIANNESS_LITTLE : ENDIANNESS_BIG;
40 : }
41 :
42 24 : static inline size_t elem_sizeof(size_t size)
43 : {
44 24 : if (size == 1 || size == 2 || size == 4 || size == 8) {
45 24 : return size;
46 : }
47 :
48 0 : return 1;
49 : }
50 :
51 10 : static inline void *conv_memcpy(void *dest, const void *src, size_t size)
52 : {
53 10 : return bswap_memcpy(dest, src, size, elem_sizeof(size));
54 : }
55 :
56 3067 : static inline void *memcpy_common(void *dest, const void *src, size_t size, bool is_native)
57 : {
58 3067 : return is_native ? pmemcpy(dest, src, size) : conv_memcpy(dest, src, size);
59 : }
60 :
61 16 : static inline void *memmove_common(void *dest, const void *src, size_t size, bool is_native)
62 : {
63 : uint8_t *tmp;
64 :
65 16 : if (is_native) {
66 8 : return pmemmove(dest, src, size);
67 : }
68 :
69 8 : tmp = (uint8_t *)pmalloc(size);
70 8 : if (tmp == NULL) {
71 0 : return NULL;
72 : }
73 :
74 8 : pmemcpy(tmp, src, size);
75 8 : bswap_memcpy(dest, tmp, size, elem_sizeof(size));
76 :
77 8 : pfree(tmp);
78 :
79 8 : return dest;
80 : }
81 :
82 12 : static inline int memcmp_common(const void *s1, const void *s2, size_t size, bool is_native)
83 : {
84 : uint8_t *tmp1, *tmp2;
85 : size_t elem_size;
86 : int result;
87 :
88 12 : if (is_native) {
89 6 : return pmemcmp(s1, s2, size);
90 : }
91 :
92 6 : tmp1 = (uint8_t *)pmalloc(size);
93 6 : tmp2 = (uint8_t *)pmalloc(size);
94 6 : if (!tmp1 || !tmp2) {
95 0 : if (tmp1) {
96 0 : pfree(tmp1);
97 : }
98 0 : if (tmp2) {
99 0 : pfree(tmp2);
100 : }
101 0 : return 0;
102 : }
103 :
104 6 : elem_size = elem_sizeof(size);
105 6 : bswap_memcpy(tmp1, s1, size, elem_size);
106 6 : bswap_memcpy(tmp2, s2, size, elem_size);
107 :
108 6 : result = pmemcmp(tmp1, tmp2, size);
109 :
110 6 : pfree(tmp1);
111 6 : pfree(tmp2);
112 :
113 6 : return result;
114 : }
115 :
116 1038 : extern void *pino_endianness_memcpy_le2native(void *dest, const void *src, size_t size)
117 : {
118 1038 : return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
119 : }
120 :
121 5 : extern void *pino_endianness_memcpy_be2native(void *dest, const void *src, size_t size)
122 : {
123 5 : return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
124 : }
125 :
126 2019 : extern void *pino_endianness_memcpy_native2le(void *dest, const void *src, size_t size)
127 : {
128 2019 : return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
129 : }
130 :
131 5 : extern void *pino_endianness_memcpy_native2be(void *dest, const void *src, size_t size)
132 : {
133 5 : return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
134 : }
135 :
136 4 : extern void *pino_endianness_memmove_le2native(void *dest, const void *src, size_t size)
137 : {
138 4 : return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
139 : }
140 :
141 3 : extern void *pino_endianness_memmove_be2native(void *dest, const void *src, size_t size)
142 : {
143 3 : return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
144 : }
145 :
146 4 : extern void *pino_endianness_memmove_native2le(void *dest, const void *src, size_t size)
147 : {
148 4 : return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
149 : }
150 :
151 5 : extern void *pino_endianness_memmove_native2be(void *dest, const void *src, size_t size)
152 : {
153 5 : return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
154 : }
155 :
156 3 : extern int pino_endianness_memcmp_le2native(const void *s1, const void *s2, size_t size)
157 : {
158 3 : return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_LITTLE));
159 : }
160 :
161 3 : extern int pino_endianness_memcmp_be2native(const void *s1, const void *s2, size_t size)
162 : {
163 3 : return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_BIG));
164 : }
165 :
166 3 : extern int pino_endianness_memcmp_native2le(const void *s1, const void *s2, size_t size)
167 : {
168 3 : return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_LITTLE));
169 : }
170 :
171 3 : extern int pino_endianness_memcmp_native2be(const void *s1, const void *s2, size_t size)
172 : {
173 3 : return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_BIG));
174 : }
|