LCOV - code coverage report
Current view: top level - gi - arg-types-inl.h (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 100.0 % 4 4
Test Date: 2025-05-21 00:02:11 Functions: 57.1 % 21 12
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
       2                 :             : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
       3                 :             : // SPDX-FileCopyrightText: 2020 Marco Trevisan <marco.trevisan@canonical.com>
       4                 :             : 
       5                 :             : #pragma once
       6                 :             : 
       7                 :             : #include <config.h>
       8                 :             : 
       9                 :             : #include <stdint.h>
      10                 :             : 
      11                 :             : #include <limits>
      12                 :             : #include <type_traits>
      13                 :             : 
      14                 :             : #include <girepository.h>
      15                 :             : #include <glib-object.h>  // for GValue
      16                 :             : #include <glib.h>         // for gboolean
      17                 :             : 
      18                 :             : namespace Gjs {
      19                 :             : 
      20                 :             : template <typename T>
      21                 :             : struct TypeWrapper {
      22                 :             :     constexpr TypeWrapper() : m_value(0) {}
      23                 :        1627 :     explicit constexpr TypeWrapper(T v) : m_value(v) {}
      24                 :             :     constexpr operator T() const { return m_value; }
      25                 :        1623 :     constexpr operator T() { return m_value; }
      26                 :             : 
      27                 :             :  private:
      28                 :             :     T m_value;
      29                 :             : };
      30                 :             : 
      31                 :             : template <typename T1, typename T2>
      32                 :             : constexpr bool comparable_types() {
      33                 :             :     return std::is_arithmetic_v<T1> == std::is_arithmetic_v<T2> &&
      34                 :             :            std::is_integral_v<T1> == std::is_integral_v<T2> &&
      35                 :             :            std::is_signed_v<T1> == std::is_signed_v<T2>;
      36                 :             : }
      37                 :             : 
      38                 :             : template <typename T, typename Container>
      39                 :             : constexpr bool type_fits() {
      40                 :             :     if constexpr (comparable_types<T, Container>()) {
      41                 :             :         return (std::numeric_limits<T>::max() <=
      42                 :             :                     std::numeric_limits<Container>::max() &&
      43                 :             :                 std::numeric_limits<T>::lowest() >=
      44                 :             :                     std::numeric_limits<Container>::lowest());
      45                 :             :     }
      46                 :             : 
      47                 :             :     return false;
      48                 :             : }
      49                 :             : 
      50                 :             : // These tags are used to disambiguate types such as gboolean and GType which
      51                 :             : // are in fact typedefs of other generic types. Using the tag instead of the
      52                 :             : // type directly allows performing proper specialization. See also arg-inl.h.
      53                 :             : namespace Tag {
      54                 :             : struct GBoolean {};
      55                 :             : struct GType {};
      56                 :             : struct Long {};
      57                 :             : struct UnsignedLong {};
      58                 :             : struct Enum {};
      59                 :             : struct UnsignedEnum {};
      60                 :             : }  // namespace Tag
      61                 :             : 
      62                 :             : template <typename TAG>
      63                 :             : struct MarshallingInfo {};
      64                 :             : 
      65                 :             : template <>
      66                 :             : struct MarshallingInfo<bool> {
      67                 :             :     using real_type = bool;
      68                 :             :     using containing_tag = bool;
      69                 :             :     using jsvalue_pack_type = int32_t;
      70                 :             :     static constexpr const char* name = "bool";
      71                 :             : };
      72                 :             : 
      73                 :             : template <>
      74                 :             : struct MarshallingInfo<int8_t> {
      75                 :             :     using real_type = int8_t;
      76                 :             :     using containing_tag = int32_t;
      77                 :             :     using jsvalue_pack_type = int32_t;
      78                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_INT8;
      79                 :             :     static constexpr const char* name = "int8";
      80                 :             : };
      81                 :             : 
      82                 :             : template <>
      83                 :             : struct MarshallingInfo<uint8_t> {
      84                 :             :     using real_type = uint8_t;
      85                 :             :     using containing_tag = uint32_t;
      86                 :             :     using jsvalue_pack_type = int32_t;
      87                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_UINT8;
      88                 :             :     static constexpr const char* name = "uint8";
      89                 :             : };
      90                 :             : 
      91                 :             : template <>
      92                 :             : struct MarshallingInfo<int16_t> {
      93                 :             :     using real_type = int16_t;
      94                 :             :     using containing_tag = int32_t;
      95                 :             :     using jsvalue_pack_type = int32_t;
      96                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_INT16;
      97                 :             :     static constexpr const char* name = "int16";
      98                 :             : };
      99                 :             : 
     100                 :             : template <>
     101                 :             : struct MarshallingInfo<uint16_t> {
     102                 :             :     using real_type = uint16_t;
     103                 :             :     using containing_tag = uint32_t;
     104                 :             :     using jsvalue_pack_type = int32_t;
     105                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_UINT16;
     106                 :             :     static constexpr const char* name = "uint16";
     107                 :             : };
     108                 :             : 
     109                 :             : template <>
     110                 :             : struct MarshallingInfo<int32_t> {
     111                 :             :     using real_type = int32_t;
     112                 :             :     using containing_tag = int32_t;
     113                 :             :     using jsvalue_pack_type = int32_t;
     114                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_INT32;
     115                 :             :     static constexpr const char* name = "int32";
     116                 :             : };
     117                 :             : 
     118                 :             : template <>
     119                 :             : struct MarshallingInfo<uint32_t> {
     120                 :             :     using real_type = uint32_t;
     121                 :             :     using containing_tag = uint32_t;
     122                 :             :     using jsvalue_pack_type = double;
     123                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_UINT32;
     124                 :             :     static constexpr const char* name = "uint32";
     125                 :             : };
     126                 :             : 
     127                 :             : template <>
     128                 :             : struct MarshallingInfo<char32_t> {
     129                 :             :     using real_type = char32_t;
     130                 :             :     using containing_tag = char32_t;
     131                 :             :     using jsvalue_pack_type = double;
     132                 :             :     static constexpr const char* name = "char32";
     133                 :             : };
     134                 :             : 
     135                 :             : template <>
     136                 :             : struct MarshallingInfo<int64_t> {
     137                 :             :     using real_type = int64_t;
     138                 :             :     using containing_tag = int64_t;
     139                 :             :     using jsvalue_pack_type = TypeWrapper<int64_t>;
     140                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_INT64;
     141                 :             :     static constexpr const char* name = "int64";
     142                 :             : };
     143                 :             : 
     144                 :             : template <>
     145                 :             : struct MarshallingInfo<uint64_t> {
     146                 :             :     using real_type = uint64_t;
     147                 :             :     using containing_tag = uint64_t;
     148                 :             :     using jsvalue_pack_type = TypeWrapper<uint64_t>;
     149                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_UINT64;
     150                 :             :     static constexpr const char* name = "uint64";
     151                 :             : };
     152                 :             : 
     153                 :             : template <>
     154                 :             : struct MarshallingInfo<float> {
     155                 :             :     using real_type = float;
     156                 :             :     using containing_tag = double;
     157                 :             :     using jsvalue_pack_type = double;
     158                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_FLOAT;
     159                 :             :     static constexpr const char* name = "float";
     160                 :             : };
     161                 :             : 
     162                 :             : template <>
     163                 :             : struct MarshallingInfo<double> {
     164                 :             :     using real_type = double;
     165                 :             :     using containing_tag = double;
     166                 :             :     using jsvalue_pack_type = double;
     167                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_DOUBLE;
     168                 :             :     static constexpr const char* name = "double";
     169                 :             : };
     170                 :             : 
     171                 :             : template <typename T>
     172                 :             : struct MarshallingInfo<T*> {
     173                 :             :     using real_type = T*;
     174                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_VOID;
     175                 :             :     static constexpr const char* name = "pointer";
     176                 :             : };
     177                 :             : 
     178                 :             : template <>
     179                 :             : struct MarshallingInfo<Tag::GType> {
     180                 :             :     using real_type = GType;
     181                 :             :     using containing_tag = Tag::GType;
     182                 :             :     using jsvalue_pack_type = TypeWrapper<uint64_t>;
     183                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_GTYPE;
     184                 :             :     static constexpr const char* name = "GType";
     185                 :             : };
     186                 :             : 
     187                 :             : template <>
     188                 :             : struct MarshallingInfo<Tag::GBoolean> {
     189                 :             :     using real_type = gboolean;
     190                 :             :     using containing_tag = Tag::GBoolean;
     191                 :             :     using jsvalue_pack_type = int32_t;
     192                 :             :     static constexpr GITypeTag gi_tag = GI_TYPE_TAG_BOOLEAN;
     193                 :             :     static constexpr const char* name = "boolean";
     194                 :             : };
     195                 :             : 
     196                 :             : template <>
     197                 :             : struct MarshallingInfo<GValue*> {
     198                 :             :     using real_type = GValue*;
     199                 :             :     static constexpr const char* name = "GValue";
     200                 :             : };
     201                 :             : 
     202                 :             : template <>
     203                 :             : struct MarshallingInfo<GValue> {
     204                 :             :     using real_type = GValue;
     205                 :             :     using containing_tag = GValue;
     206                 :             :     static constexpr const char* name = "flat GValue";
     207                 :             : };
     208                 :             : 
     209                 :             : template <>
     210                 :             : struct MarshallingInfo<char*> {
     211                 :             :     using real_type = char*;
     212                 :             :     using containing_tag = char*;
     213                 :             :     using jsvalue_pack_type = char*;
     214                 :             :     static constexpr const char* name = "string";
     215                 :             : };
     216                 :             : 
     217                 :             : template <>
     218                 :             : struct MarshallingInfo<const char*> {
     219                 :             :     using real_type = const char*;
     220                 :             :     static constexpr const char* name = "constant string";
     221                 :             : };
     222                 :             : 
     223                 :             : template <>
     224                 :             : struct MarshallingInfo<Tag::Long> {
     225                 :             :     static constexpr bool is_32 =
     226                 :             :         type_fits<long, int32_t>();  // NOLINT(runtime/int)
     227                 :             :     using real_type = long;  // NOLINT(runtime/int)
     228                 :             :     using containing_tag = std::conditional_t<is_32, int32_t, int64_t>;
     229                 :             :     using jsvalue_pack_type =
     230                 :             :         std::conditional_t<is_32, int32_t, TypeWrapper<int64_t>>;
     231                 :             :     static constexpr const char* name = "long";
     232                 :             : };
     233                 :             : 
     234                 :             : template <>
     235                 :             : struct MarshallingInfo<Tag::UnsignedLong> {
     236                 :             :     static constexpr bool is_32 =
     237                 :             :         type_fits<unsigned long, uint32_t>();  // NOLINT(runtime/int)
     238                 :             :     using real_type = unsigned long;  // NOLINT(runtime/int)
     239                 :             :     using containing_tag = std::conditional_t<is_32, uint32_t, uint64_t>;
     240                 :             :     using jsvalue_pack_type =
     241                 :             :         std::conditional_t<is_32, double, TypeWrapper<uint64_t>>;
     242                 :             :     static constexpr const char* name = "unsigned long";
     243                 :             : };
     244                 :             : 
     245                 :             : template <>
     246                 :             : struct MarshallingInfo<Tag::Enum> {
     247                 :             :     using real_type = int;
     248                 :             :     using containing_tag = int32_t;
     249                 :             :     using jsvalue_pack_type = int32_t;
     250                 :             : };
     251                 :             : 
     252                 :             : template <>
     253                 :             : struct MarshallingInfo<Tag::UnsignedEnum> {
     254                 :             :     using real_type = unsigned int;
     255                 :             :     using containing_tag = uint32_t;
     256                 :             :     using jsvalue_pack_type = double;
     257                 :             : };
     258                 :             : 
     259                 :             : template <>
     260                 :             : struct MarshallingInfo<void> {
     261                 :             :     using real_type = void;
     262                 :             : };
     263                 :             : 
     264                 :             : namespace Tag {
     265                 :             : template <typename TAG>
     266                 :             : using RealT = typename MarshallingInfo<TAG>::real_type;
     267                 :             : 
     268                 :             : // There are two ways you can unpack a C value from a JSValue.
     269                 :             : // The containing type is the most appropriate C type that can contain the
     270                 :             : // unpacked value. Implicit conversion may be performed and the value may need
     271                 :             : // to be checked to make sure it is in range.
     272                 :             : // The JSValue pack type, on the other hand, is the C type that is exactly
     273                 :             : // equivalent to how JSValue stores the value, so no implicit conversion is
     274                 :             : // performed unless the JSValue contains a pointer to a GC-thing, like BigInt.
     275                 :             : template <typename TAG>
     276                 :             : using JSValueContainingT = RealT<typename MarshallingInfo<TAG>::containing_tag>;
     277                 :             : 
     278                 :             : template <typename TAG>
     279                 :             : using JSValueContainingTag = typename MarshallingInfo<TAG>::containing_tag;
     280                 :             : 
     281                 :             : template <typename TAG>
     282                 :             : using JSValuePackT = typename MarshallingInfo<TAG>::jsvalue_pack_type;
     283                 :             : 
     284                 :             : template <typename TAG>
     285                 :             : using JSValuePackTag = std::conditional_t<
     286                 :             :     std::is_same_v<JSValuePackT<TAG>, TypeWrapper<int64_t>>, int64_t,
     287                 :             :     std::conditional_t<std::is_same_v<JSValuePackT<TAG>, TypeWrapper<uint64_t>>,
     288                 :             :                        uint64_t, JSValuePackT<TAG>>>;
     289                 :             : }  // namespace Tag
     290                 :             : 
     291                 :             : template <typename TAG>
     292                 :          26 : constexpr inline const char* static_type_name() {
     293                 :          26 :     return MarshallingInfo<TAG>::name;
     294                 :             : }
     295                 :             : 
     296                 :             : }  // namespace Gjs
        

Generated by: LCOV version 2.0-1