Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/third_party/rlbox/include/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  rlbox_conversion.hpp   Sprache: C

 
#pragma once
// IWYU pragma: private, include "rlbox.hpp"
// IWYU pragma: friend "rlbox_.*\.hpp"

#include <array>
#include <cstring>
#include <limits>
#include <type_traits>

#include "rlbox_helpers.hpp"
#include "rlbox_type_traits.hpp"
#include "rlbox_types.hpp"

namespace rlbox::detail {

template<typename T_To, typename T_From>
inline constexpr void convert_type_fundamental(T_To& to,
                                               const volatile T_From& from)
{
  using namespace std;

  if_constexpr_named(cond1, !is_fundamental_or_enum_v<T_To>)
  {
    rlbox_detail_static_fail_because(
      cond1, "Conversion target should be fundamental or enum type");
  }
  else if_constexpr_named(cond2, !is_fundamental_or_enum_v<T_From>)
  {
    rlbox_detail_static_fail_because(
      cond2, "Conversion source should be fundamental or enum type");
  }
  else if_constexpr_named(cond3, is_enum_v<T_To> || is_enum_v<T_From>)
  {
    static_assert(std::is_same_v<detail::remove_cv_ref_t<T_To>,
                                 detail::remove_cv_ref_t<T_From>>);
    to = from;
  }
  else if_constexpr_named(
    cond4, is_floating_point_v<T_To> || is_floating_point_v<T_From>)
  {
    static_assert(is_floating_point_v<T_To> && is_floating_point_v<T_From>);
    // language coerces different float types
    to = from;
  }
  else if_constexpr_named(cond5, is_integral_v<T_To> || is_integral_v<T_From>)
  {
    static_assert(is_integral_v<T_To> && is_integral_v<T_From>);

    const char* err_msg =
      "Over/Underflow when converting between integer types";

    // Some branches don't use the param
    RLBOX_UNUSED(err_msg);

    if constexpr (is_signed_v<T_To> == is_signed_v<T_From> &&
                  sizeof(T_To) >= sizeof(T_From)) {
      // Eg: int64_t from int32_t, uint64_t from uint32_t
    } else if constexpr (is_unsigned_v<T_To> && is_unsigned_v<T_From>) {
      // Eg: uint32_t from uint64_t
      dynamic_check(from <= numeric_limits<T_To>::max(), err_msg);
    } else if constexpr (is_signed_v<T_To> && is_signed_v<T_From>) {
      // Eg: int32_t from int64_t
      dynamic_check(from >= numeric_limits<T_To>::min(), err_msg);
      dynamic_check(from <= numeric_limits<T_To>::max(), err_msg);
    } else if constexpr (is_unsigned_v<T_To> && is_signed_v<T_From>) {
      if constexpr (sizeof(T_To) < sizeof(T_From)) {
        // Eg: uint32_t from int64_t
        dynamic_check(from >= 0, err_msg);
        auto to_max = numeric_limits<T_To>::max();
        dynamic_check(from <= static_cast<T_From>(to_max), err_msg);
      } else {
        // Eg: uint32_t from int32_t, uint64_t from int32_t
        dynamic_check(from >= 0, err_msg);
      }
    } else if constexpr (is_signed_v<T_To> && is_unsigned_v<T_From>) {
      if constexpr (sizeof(T_To) <= sizeof(T_From)) {
        // Eg: int32_t from uint32_t, int32_t from uint64_t
        auto to_max = numeric_limits<T_To>::max();
        dynamic_check(from <= static_cast<T_From>(to_max), err_msg);
      } else {
        // Eg: int64_t from uint32_t
      }
    }
    to = static_cast<T_To>(from);
  }
  else
  {
    constexpr auto unknownCase = !(cond1 || cond2 || cond3 || cond4 || cond5);
    rlbox_detail_static_fail_because(
      unknownCase, "Unexpected case for convert_type_fundamental");
  }
}

template<typename T_To, typename T_From>
inline constexpr void convert_type_fundamental_or_array(T_To& to,
                                                        const T_From& from)
{
  using namespace std;

  using T_To_C = std_array_to_c_arr_t<T_To>;
  using T_From_C = std_array_to_c_arr_t<T_From>;
  using T_To_El = remove_all_extents_t<T_To_C>;
  using T_From_El = remove_all_extents_t<T_From_C>;

  if_constexpr_named(cond1, is_array_v<T_To_C> != is_array_v<T_From_C>)
  {
    rlbox_detail_static_fail_because(
      cond1, "Conversion should not go between array and non array types");
  }
  else if constexpr (!is_array_v<T_To_C>)
  {
    convert_type_fundamental(to, from);
  }
  else if_constexpr_named(cond2, !all_extents_same<T_To_C, T_From_C>)
  {
    rlbox_detail_static_fail_because(
      cond2, "Conversion between arrays should have same dimensions");
  }
  else if_constexpr_named(cond3,
                          is_pointer_v<T_To_El> || is_pointer_v<T_From_El>)
  {
    rlbox_detail_static_fail_because(cond3,
                                     "convert_type_fundamental_or_array "
                                     "does not allow arrays of pointers");
  }
  else
  {
    // Explicitly using size to check for element type as we may be going across
    // different types of the same width such as void* and uintptr_t
    if constexpr (sizeof(T_To_El) == sizeof(T_From_El) &&
                  is_signed_v<T_To_El> == is_signed_v<T_From_El>) {
      // Sanity check - this should definitely be true
      static_assert(sizeof(T_From_C) == sizeof(T_To_C));
      std::memcpy(&to, &from, sizeof(T_To_C));
    } else {
      for (size_t i = 0; i < std::extent_v<T_To_C>; i++) {
        convert_type_fundamental_or_array(to[i], from[i]);
      }
    }
  }
}

enum class adjust_type_direction
{
  TO_SANDBOX,
  TO_APPLICATION,
  NO_CHANGE
};

enum class adjust_type_context
{
  EXAMPLE,
  SANDBOX
};

template<typename T_Sbx,
         adjust_type_direction Direction,
         adjust_type_context Context,
         typename T_To,
         typename T_From>
inline constexpr void convert_type_non_class(
  T_To& to,
  const T_From& from,
  const void* example_unsandboxed_ptr,
  rlbox_sandbox<T_Sbx>* sandbox_ptr)
{
  using namespace std;

  // Some branches don't use the param
  RLBOX_UNUSED(example_unsandboxed_ptr);
  RLBOX_UNUSED(sandbox_ptr);

  using T_To_C = std_array_to_c_arr_t<T_To>;
  using T_From_C = std_array_to_c_arr_t<T_From>;
  using T_To_El = remove_all_extents_t<T_To_C>;
  using T_From_El = remove_all_extents_t<T_From_C>;

  if constexpr (is_pointer_v<T_To_C> || is_pointer_v<T_From_C>) {

    if constexpr (Direction == adjust_type_direction::NO_CHANGE) {

      static_assert(is_pointer_v<T_To_C> && is_pointer_v<T_From_C> &&
                    sizeof(T_To_C) == sizeof(T_From_C));
      to = from;

    } else if constexpr (Direction == adjust_type_direction::TO_SANDBOX) {

      static_assert(is_pointer_v<T_From_C>);
      // Maybe a function pointer, so convert
      auto from_c = reinterpret_cast<const void*>(from);
      if constexpr (Context == adjust_type_context::SANDBOX) {
        RLBOX_DEBUG_ASSERT(sandbox_ptr != nullptr);
        to = sandbox_ptr->template get_sandboxed_pointer<T_From_C>(from_c);
      } else {
        RLBOX_DEBUG_ASSERT(from_c == nullptr ||
                           example_unsandboxed_ptr != nullptr);
        to =
          rlbox_sandbox<T_Sbx>::template get_sandboxed_pointer_no_ctx<T_From_C>(
            from_c, example_unsandboxed_ptr);
      }

    } else if constexpr (Direction == adjust_type_direction::TO_APPLICATION) {

      static_assert(is_pointer_v<T_To_C>);
      if constexpr (Context == adjust_type_context::SANDBOX) {
        RLBOX_DEBUG_ASSERT(sandbox_ptr != nullptr);
        to = sandbox_ptr->template get_unsandboxed_pointer<T_To_C>(from);
      } else {
        RLBOX_DEBUG_ASSERT(from == 0 || example_unsandboxed_ptr != nullptr);
        to =
          rlbox_sandbox<T_Sbx>::template get_unsandboxed_pointer_no_ctx<T_To_C>(
            from, example_unsandboxed_ptr);
      }
    }

  } else if constexpr (is_pointer_v<T_To_El> || is_pointer_v<T_From_El>) {

    if constexpr (Direction == adjust_type_direction::NO_CHANGE) {
      // Sanity check - this should definitely be true
      static_assert(sizeof(T_To_El) == sizeof(T_From_El) &&
                    sizeof(T_From_C) == sizeof(T_To_C));
      memcpy(&to, &from, sizeof(T_To_C));
    } else {
      for (size_t i = 0; i < std::extent_v<T_To_C>; i++) {
        convert_type_non_class<T_Sbx, Direction, Context>(
          to[i], from[i], example_unsandboxed_ptr, sandbox_ptr);
      }
    }

  } else {
    convert_type_fundamental_or_array(to, from);
  }
}

// Structs implement their own convert_type by specializing this class
// Have to do this via a class, as functions can't be partially specialized
template<typename T_Sbx,
         adjust_type_direction Direction,
         adjust_type_context Context,
         typename T_To,
         typename T_From>
class convert_type_class;
// The specialization implements the following
// {
//   static inline void run(T_To& to,
//                          const T_From& from,
//                          const void* example_unsandboxed_ptr);
// }

template<typename T_Sbx,
         adjust_type_direction Direction,
         adjust_type_context Context,
         typename T_To,
         typename T_From>
inline void convert_type(T_To& to,
                         const T_From& from,
                         const void* example_unsandboxed_ptr,
                         rlbox_sandbox<T_Sbx>* sandbox_ptr)
{
  if constexpr ((std::is_class_v<T_To> ||
                 std::is_class_v<T_From>)&&!detail::is_std_array_v<T_To> &&
                !detail::is_std_array_v<T_From>) {
    // Sanity check
    static_assert(std::is_class_v<T_From> && std::is_class_v<T_To>);
    convert_type_class<T_Sbx, Direction, Context, T_To, T_From>::run(
      to, from, example_unsandboxed_ptr, sandbox_ptr);
  } else {
    convert_type_non_class<T_Sbx, Direction, Context>(
      to, from, example_unsandboxed_ptr, sandbox_ptr);
  }
}

}

Messung V0.5
C=94 H=98 G=95

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.