LCOV - code coverage report
Current view: top level - src - endianness.c (source / functions) Coverage Total Hit
Test: pino Coverage Report Lines: 100.0 % 96 96
Test Date: 2025-04-10 02:21:08 Functions: 100.0 % 22 22
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * libpino - endianness.c
       3              :  * 
       4              :  * Copyright (c) 2025 Go Kudo
       5              :  *
       6              :  * This library is licensed under the BSD 3-Clause License.
       7              :  * For license details, please refer to the LICENSE file.
       8              :  *
       9              :  * SPDX-FileCopyrightText: Go Kudo <zeriyoshi@gmail.com>
      10              :  * SPDX-License-Identifier: BSD-3-Clause
      11              :  */
      12              : 
      13              : #include <pino/endianness.h>
      14              : 
      15              : #include <pino_internal.h>
      16              : 
      17              : #define ENDIANNESS_UNKNOWN      0
      18              : #define ENDIANNESS_LITTLE       1
      19              : #define ENDIANNESS_BIG          2
      20              : 
      21              : #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      22              : static uint8_t g_endianness = ENDIANNESS_LITTLE;
      23              : #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      24              : static uint8_t g_endianness = ENDIANNESS_BIG;
      25              : #else
      26              : static uint8_t g_endianness = ENDIANNESS_UNKNOWN;
      27              : #endif
      28              : 
      29         3094 : static inline uint8_t platform_endianness(void)
      30              : {
      31              :     uint32_t i;
      32              :     uint8_t *p;
      33              :     
      34         3094 :     if (g_endianness != ENDIANNESS_UNKNOWN) {
      35         3094 :         return g_endianness;
      36              :     }
      37              : 
      38              :     /* LCOV_EXCL_START */
      39              : 
      40              :     i = 1;
      41              :     p = (uint8_t *)&i;
      42              : 
      43              :     return g_endianness = (p[0] == 1) ? ENDIANNESS_LITTLE : ENDIANNESS_BIG;
      44              : 
      45              :     /* LCOV_EXCL_STOP */
      46              : }
      47              : 
      48            4 : static inline uint16_t bswap16(uint16_t x)
      49              : {
      50            4 :     return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);
      51              : }
      52              : 
      53           16 : static inline uint32_t bswap32(uint32_t x)
      54              : {
      55           16 :     return ((x & 0xff) << 24) | 
      56           16 :            ((x & 0xff00) << 8) | 
      57           32 :            ((x & 0xff0000) >> 8) | 
      58           16 :            ((x & 0xff000000) >> 24);
      59              : }
      60              : 
      61            6 : static inline uint64_t bswap64(uint64_t x)
      62              : {
      63            6 :     return ((x & 0xff) << 56) | 
      64            6 :            ((x & 0xff00) << 40) | 
      65            6 :            ((x & 0xff0000) << 24) | 
      66            6 :            ((x & 0xff000000) << 8) | 
      67            6 :            ((x & 0xff00000000ULL) >> 8) | 
      68            6 :            ((x & 0xff0000000000ULL) >> 24) | 
      69           12 :            ((x & 0xff000000000000ULL) >> 40) | 
      70            6 :            ((x & 0xff00000000000000ULL) >> 56);
      71              : }
      72              : 
      73           30 : static inline void *bswap_memcpy(void *dest, const void *src, size_t size, size_t elem_size)
      74              : {
      75              :     uint8_t *dp;
      76              :     const uint8_t *sp;
      77              :     size_t i, j;
      78              :     uint16_t *dest16, *src16;
      79              :     uint32_t *dest32, *src32;
      80              :     uint64_t *dest64, *src64;
      81              : 
      82           30 :     dp = (uint8_t *)dest;
      83           30 :     sp = (const uint8_t *)src;
      84              : 
      85           30 :     if (elem_size == 1 || size == 0) {
      86            2 :         return pmemcpy(dest, src, size);
      87              :     }
      88              : 
      89           28 :     if (elem_size == 2 && (((uintptr_t)dest | (uintptr_t)src) & 0x1) == 0) {
      90            4 :         dest16 = (uint16_t *)dest;
      91            4 :         src16 = (uint16_t *)src;
      92              : 
      93            8 :         for (i = 0; i < size / 2; i++) {
      94            4 :             dest16[i] = bswap16(src16[i]);
      95              :         }
      96              : 
      97            4 :         return dest;
      98           24 :     } else if (elem_size == 4 && (((uintptr_t)dest | (uintptr_t)src) & 0x3) == 0) {
      99           16 :         dest32 = (uint32_t *)dest;
     100           16 :         src32 = (uint32_t *)src;
     101              : 
     102           32 :         for (i = 0; i < size / 4; i++) {
     103           16 :             dest32[i] = bswap32(src32[i]);
     104              :         }
     105              : 
     106           16 :         return dest;
     107            8 :     } else if (elem_size == 8 && (((uintptr_t)dest | (uintptr_t)src) & 0x7) == 0) {
     108            6 :         dest64 = (uint64_t *)dest;
     109            6 :         src64 = (uint64_t *)src;
     110              : 
     111           12 :         for (i = 0; i < size / 8; i++) {
     112            6 :             dest64[i] = bswap64(src64[i]);
     113              :         }
     114              : 
     115            6 :         return dest;
     116              :     }
     117              : 
     118            4 :     for (i = 0; i < size; i += elem_size) {
     119            6 :         for (j = 0; j < elem_size; j++) {
     120            4 :             dp[i + j] = sp[i + (elem_size - 1 - j)];
     121              :         }
     122              :     }
     123              : 
     124            2 :     return dest;
     125              : }
     126              : 
     127           24 : static inline size_t elem_sizeof(size_t size)
     128              : {
     129           24 :     return (size % 8 == 0) ? 8 : (size % 4 == 0) ? 4 : (size % 2 == 0) ? 2 : 1;
     130              : }
     131              : 
     132           10 : static inline void *conv_memcpy(void *dest, const void *src, size_t size)
     133              : {
     134           10 :     return bswap_memcpy(dest, src, size, elem_sizeof(size));
     135              : }
     136              : 
     137         3066 : static inline void *memcpy_common(void *dest, const void *src, size_t size, bool is_native)
     138              : {
     139         3066 :     return is_native ? pmemcpy(dest, src, size) : conv_memcpy(dest, src, size);
     140              : }
     141              : 
     142           16 : static inline void *memmove_common(void *dest, const void *src, size_t size, bool is_native)
     143              : {
     144              :     uint8_t *tmp;
     145              : 
     146           16 :     if (is_native) {
     147            8 :         return pmemmove(dest, src, size);
     148              :     } else {
     149            8 :         tmp = (uint8_t *)pmalloc(size);
     150              :         /* LCOV_EXCL_START */
     151              :         if (tmp == NULL) {
     152              :             PINO_SUPRTF("pmalloc failed");
     153              :             return NULL;
     154              :         }
     155              :         /* LCOV_EXCL_STOP */
     156              : 
     157            8 :         pmemcpy(tmp, src, size);
     158            8 :         bswap_memcpy(dest, tmp, size, elem_sizeof(size));
     159              : 
     160            8 :         pfree(tmp);
     161              : 
     162            8 :         return dest;
     163              :     }
     164              : 
     165              :     /* LCOV_EXCL_START */
     166              :     PINO_SUPUNREACH();
     167              :     return NULL;
     168              :     /* LCOV_EXCL_STOP */
     169              : }
     170              : 
     171           12 : static inline int memcmp_common(const void *s1, const void *s2, size_t size, bool is_native)
     172              : {
     173              :     uint8_t *tmp1, *tmp2;
     174              :     size_t elem_size;
     175              :     int result;
     176              : 
     177           12 :     if (is_native) {
     178            6 :         return pmemcmp(s1, s2, size);
     179              :     } else {
     180            6 :         tmp1 = (uint8_t *)pmalloc(size);
     181            6 :         tmp2 = (uint8_t *)pmalloc(size);
     182              :         /* LCOV_EXCL_START */
     183              :         if (!tmp1 || !tmp2) {
     184              :             PINO_SUPRTF("pmalloc failed");
     185              : 
     186              :             if (tmp1) {
     187              :                 pfree(tmp1);
     188              :             }
     189              : 
     190              :             if (tmp2) {
     191              :                 pfree(tmp2);
     192              :             }
     193              : 
     194              :             return 0;
     195              :         }
     196              :         /* LCOV_EXCL_STOP */
     197              : 
     198            6 :         elem_size = elem_sizeof(size);
     199            6 :         bswap_memcpy(tmp1, s1, size, elem_size);
     200            6 :         bswap_memcpy(tmp2, s2, size, elem_size);
     201              : 
     202            6 :         result = pmemcmp(tmp1, tmp2, size);
     203              : 
     204            6 :         pfree(tmp1);
     205            6 :         pfree(tmp2);
     206              : 
     207            6 :         return result;
     208              :     }
     209              : 
     210              :     /* LCOV_EXCL_START */
     211              :     PINO_SUPUNREACH();
     212              :     return 0;
     213              :     /* LCOV_EXCL_STOP */
     214              : }
     215              : 
     216         1037 : extern void *pino_endianness_memcpy_le2native(void *dest, const void *src, size_t size)
     217              : {    
     218         1037 :     return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
     219              : }
     220              : 
     221            5 : extern void *pino_endianness_memcpy_be2native(void *dest, const void *src, size_t size)
     222              : {   
     223            5 :     return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
     224              : }
     225              : 
     226         2019 : extern void *pino_endianness_memcpy_native2le(void *dest, const void *src, size_t size)
     227              : {
     228         2019 :     return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
     229              : }
     230              : 
     231            5 : extern void *pino_endianness_memcpy_native2be(void *dest, const void *src, size_t size)
     232              : {
     233            5 :     return memcpy_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));    
     234              : }
     235              : 
     236            4 : extern void *pino_endianness_memmove_le2native(void *dest, const void *src, size_t size)
     237              : {
     238            4 :     return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
     239              : }
     240              : 
     241            3 : extern void *pino_endianness_memmove_be2native(void *dest, const void *src, size_t size)
     242              : {
     243            3 :     return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
     244              : }
     245              : 
     246            4 : extern void *pino_endianness_memmove_native2le(void *dest, const void *src, size_t size)
     247              : {
     248            4 :     return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_LITTLE));
     249              : }
     250              : 
     251            5 : extern void *pino_endianness_memmove_native2be(void *dest, const void *src, size_t size)
     252              : {
     253            5 :     return memmove_common(dest, src, size, (platform_endianness() == ENDIANNESS_BIG));
     254              : }
     255              : 
     256            3 : extern int pino_endianness_memcmp_le2native(const void *s1, const void *s2, size_t size)
     257              : {
     258            3 :     return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_LITTLE));
     259              : }
     260              : 
     261            3 : extern int pino_endianness_memcmp_be2native(const void *s1, const void *s2, size_t size)
     262              : {
     263            3 :     return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_BIG));
     264              : }
     265              : 
     266            3 : extern int pino_endianness_memcmp_native2le(const void *s1, const void *s2, size_t size)
     267              : {
     268            3 :     return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_LITTLE));
     269              : }
     270              : 
     271            3 : extern int pino_endianness_memcmp_native2be(const void *s1, const void *s2, size_t size)
     272              : {
     273            3 :     return memcmp_common(s1, s2, size, (platform_endianness() == ENDIANNESS_BIG));
     274              : }
        

Generated by: LCOV version 2.0-1