From c4008906f4a4d379943785c0de8c6743044775be Mon Sep 17 00:00:00 2001 From: FLN1021 <14295482+fln1021@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:06:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E6=9B=B4=E6=94=B9=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/CMakeLists.txt | 1 + app/src/main/cpp/decodeMessage.cpp | 15 +- app/src/main/cpp/demod.cpp | 168 ++++++++-------- app/src/main/cpp/demod.h | 16 +- app/src/main/cpp/native-lib.cpp | 71 ++++--- app/src/main/cpp/util/qtypes.h | 301 +++++++++++++++++++++++++++++ 6 files changed, 459 insertions(+), 113 deletions(-) create mode 100644 app/src/main/cpp/util/qtypes.h diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 56d8434..72d8918 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -31,6 +31,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED native-lib.cpp decodeMessage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dsp/firfilter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dsp/hbfiltertraits.cpp native-lib.cpp) diff --git a/app/src/main/cpp/decodeMessage.cpp b/app/src/main/cpp/decodeMessage.cpp index 5585638..5da9f7e 100644 --- a/app/src/main/cpp/decodeMessage.cpp +++ b/app/src/main/cpp/decodeMessage.cpp @@ -60,17 +60,20 @@ std::string decode_gb2312(const std::string &numeric_field) { ParsedMessage p; ParsedMessage parseMessage(const std::string &msg) { // 简化:用前缀区分地址类型 - if (msg.find("1234002") != std::string::npos) { + if (msg.find("1234002") != std::string::npos && msg.size() > 50) { // 越界检查 p.vehicleId = msg.substr(15, 8); - std::string routeRaw = msg.substr(25, 14); + std::string routeRaw = msg.substr(25, 16); // 一共四个字 std::string latRaw = msg.substr(50, 8); std::string lonRaw = msg.substr(41, 9); - double latitude = std::stod(latRaw.substr(0, 2) + "." + latRaw.substr(2)); - double longitude = std::stod(lonRaw.substr(0, 3) + "." + lonRaw.substr(3)); + try { // 防止stod异常字符导致崩溃 + double latitude = std::stod(latRaw.substr(0, 2) + "." + latRaw.substr(2)); + double longitude = std::stod(lonRaw.substr(0, 3) + "." + lonRaw.substr(3)); + p.latitude = std::to_string(latitude); + p.longitude = std::to_string(longitude); + } catch (const std::invalid_argument& e) {} + catch (const std::out_of_range& e) {} - p.latitude = std::to_string(latitude); - p.longitude = std::to_string(longitude); p.route = decode_gb2312(routeRaw); } else if (msg.find("1234000") != std::string::npos) { diff --git a/app/src/main/cpp/demod.cpp b/app/src/main/cpp/demod.cpp index bf95ff7..5b90508 100644 --- a/app/src/main/cpp/demod.cpp +++ b/app/src/main/cpp/demod.cpp @@ -9,14 +9,13 @@ MovingAverageUtil preambleMovingAverage; bool got_SC = false; double dc_offset = 0.0; bool prev_data, bit_inverted, data_bit; -int sync_cnt, bit_cnt = 0, word_cnt = 0; +int bit_cnt = 0, word_cnt = 0; uint32_t bits; uint32_t code_words[PAGERDEMOD_BATCH_WORDS]; bool code_words_bch_error[PAGERDEMOD_BATCH_WORDS]; -std::string numeric_msg, alpha_msg; +std::unique_ptr> msg; // 这个其实有点激进,可能还有一些问题需要解决 int function_bits; -uint32_t address; uint32_t alpha_bit_buffer; // Bit buffer to 7-bit chars spread across codewords int alpha_bit_buffer_bits; // Count of bits in alpha_bit_buffer int parity_errors; // Count of parity errors in current message @@ -25,6 +24,9 @@ int batch_num; // Count of batches in current transmission double magsqRaw; +float sym_phase = 0.0; +const float phaseinc = BAUD_RATE / SAMPLE_RATE; + int pop_cnt(uint32_t cw) { int cnt = 0; for (int i = 0; i < 32; i++) { @@ -183,6 +185,7 @@ uint32_t reverse(uint32_t x) void decodeBatch() { int i = 1; + msg = std::make_unique>(); for (int frame = 0; frame < PAGERDEMOD_FRAMES_PER_BATCH; frame++) { for (int word = 0; word < PAGERDEMOD_CODEWORDS_PER_FRAME; word++) @@ -192,18 +195,19 @@ void decodeBatch() // Check parity bit bool parityError = !evenParity(code_words[i], 1, 31, code_words[i] & 0x1); - if (code_words[i] == PAGERDEMOD_POCSAG_IDLECODE) + if (pop_cnt(code_words[i] ^ PAGERDEMOD_POCSAG_IDLECODE) <= 3) // 0x7a89c196貌似也能过bch,不过好像只是错了一位的IDLE { // Idle + break; } else if (addressCodeWord) { // Address + msg->push_back({}); function_bits = (code_words[i] >> 11) & 0x3; + msg->back().func = function_bits; int addressBits = (code_words[i] >> 13) & 0x3ffff; - address = (addressBits << 3) | frame; - numeric_msg = ""; - alpha_msg = ""; + msg->back().addr = (addressBits << 3) | frame; alpha_bit_buffer_bits = 0; alpha_bit_buffer = 0; parity_errors = parityError ? 1 : 0; @@ -212,6 +216,8 @@ void decodeBatch() else { // Message - decode as both numeric and ASCII - not all operators use functionBits to indidcate encoding + if (msg->empty()) + msg->push_back({}); int messageBits = (code_words[i] >> 11) & 0xfffff; if (parityError) { parity_errors++; @@ -230,7 +236,7 @@ void decodeBatch() '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'U', ' ', '-', ')', '(' }; char numericChar = numericChars[numericBits]; - numeric_msg.push_back(numericChar); + msg->back().numeric.push_back(numericChar); } // 7-bit ASCII alpnanumeric format @@ -244,7 +250,7 @@ void decodeBatch() c = reverse(c) >> (32-7); // Add to received message string (excluding, null, end of text, end ot transmission) if (c != 0 && c != 0x3 && c != 0x4) { - alpha_msg.push_back(c); + msg->back().alpha.push_back(c); } // Remove from bit buffer alpha_bit_buffer_bits -= 7; @@ -262,11 +268,9 @@ void decodeBatch() } } -void processOneSample(int8_t i, int8_t q) { - float fi = ((float) i) / 128.0f; - float fq = ((float) q) / 128.0f; +void processOneSample(float i, float q) { - std::complex iq(fi, fq); + std::complex iq(i, q); float deviation; double fmDemod = phaseDiscri.phaseDiscriminatorDelta(iq, magsqRaw, deviation); @@ -283,88 +287,100 @@ void processOneSample(int8_t i, int8_t q) { // printf("filt - dc: %.3f\n", filt - dc_offset); if (data != prev_data) { - sync_cnt = SAMPLES_PER_SYMBOL / 2; // reset - } else { - sync_cnt--; // wait until next bit's midpoint - - if (sync_cnt <= 0) { - if (bit_inverted) { - data_bit = data; - } else { - data_bit = !data; - } + /* + MultimonNG的时钟同步机制,具体可参考https://github.com/EliasOenal/multimon-ng/blob/master/demod_poc12.c + 其主要为每sample给符号相位记录值sym_phase加一个增量phaseinc,之每发生位翻转时判断如果sym_phase不等于0.5就加上或减去一个 + phaseinc/2的偏移量,以确保当sym_phase等于1.0读出时样本位于符号中间。采用微调偏移量而不是像原sdrangel代码那样直接重置符号 + 相位为0.5是因为FSK在实际接收种经常会出现符号中间抖动的情况,低通滤不干净这种抖动,如果因为这种抖动造成的位翻转而重置的话会导致后 + 面的符号丢失同步。 + MultimonNG原代码中单次偏移量为phaseinc/8,根据其采用的11025hz采样率估算偏移一个符号周期大约需要73.5次偏移。由于这里采样率 + 不同故采用根据估算为偏移一个符号周期需80次偏移的phasinc/2为单次偏移量。 + */ + if (sym_phase < 0.5 - phaseinc / 2) + sym_phase += phaseinc / 2; + else + sym_phase -= phaseinc / 2; + } + sym_phase += phaseinc; - // printf("%d", data_bit); + if (sym_phase >= 1.0) { + sym_phase -= 1.0; - bits = (bits << 1) | data_bit; - bit_cnt++; + if (bit_inverted) { + data_bit = data; + } else { + data_bit = !data; + } - if (bit_cnt > 32) { - bit_cnt = 32; - } + // printf("%d", data_bit); + + bits = (bits << 1) | data_bit; + bit_cnt++; - if (bit_cnt == 32 && !got_SC) { - // printf("pop count: %d\n", pop_cnt(bits ^ POCSAG_SYNCCODE)); - // printf("pop count inv: %d\n", pop_cnt(bits ^ POCSAG_SYNCCODE_INV)); + if (bit_cnt > 32) { + bit_cnt = 32; + } - if (bits == POCSAG_SYNCCODE) { + if (bit_cnt == 32 && !got_SC) { + // printf("pop count: %d\n", pop_cnt(bits ^ POCSAG_SYNCCODE)); + // printf("pop count inv: %d\n", pop_cnt(bits ^ POCSAG_SYNCCODE_INV)); + + if (bits == POCSAG_SYNCCODE) { + got_SC = true; + bit_inverted = false; + printf("\nSync code found\n"); + } else if (bits == POCSAG_SYNCCODE_INV) { + got_SC = true; + bit_inverted = true; + printf("\nSync code found\n"); + } else if (pop_cnt(bits ^ POCSAG_SYNCCODE) <= 3) { + uint32_t corrected_cw; + if (bchDecode(bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) { got_SC = true; bit_inverted = false; printf("\nSync code found\n"); - } else if (bits == POCSAG_SYNCCODE_INV) { + } + // else printf("\nSync code not found\n"); + } else if (pop_cnt(bits ^ POCSAG_SYNCCODE_INV) <= 3) { + uint32_t corrected_cw; + if (bchDecode(~bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) { got_SC = true; bit_inverted = true; printf("\nSync code found\n"); - } else if (pop_cnt(bits ^ POCSAG_SYNCCODE) <= 3) { - uint32_t corrected_cw; - if (bchDecode(bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) { - got_SC = true; - bit_inverted = false; - printf("\nSync code found\n"); - } - // else printf("\nSync code not found\n"); - } else if (pop_cnt(bits ^ POCSAG_SYNCCODE_INV) <= 3) { - uint32_t corrected_cw; - if (bchDecode(~bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) { - got_SC = true; - bit_inverted = true; - printf("\nSync code found\n"); - } - // else printf("\nSync code not found\n"); - } - - if (got_SC) { - bits = 0; - bit_cnt = 0; - code_words[0] = POCSAG_SYNCCODE; - word_cnt = 1; - } - } else if (bit_cnt == 32 && got_SC) { - uint32_t corrected_cw; - code_words_bch_error[word_cnt] = !bchDecode(bits, corrected_cw); - code_words[word_cnt] = corrected_cw; - word_cnt++; - - if (word_cnt == 1 && corrected_cw != POCSAG_SYNCCODE) { - got_SC = false; - bit_inverted = false; - } - - if (word_cnt == PAGERDEMOD_BATCH_WORDS) { - decodeBatch(); - batch_num++; - word_cnt = 0; } + // else printf("\nSync code not found\n"); + } + if (got_SC) { bits = 0; bit_cnt = 0; - + code_words[0] = POCSAG_SYNCCODE; + word_cnt = 1; + } + } else if (bit_cnt == 32 && got_SC) { + uint32_t corrected_cw; + code_words_bch_error[word_cnt] = !bchDecode(bits, corrected_cw); + code_words[word_cnt] = corrected_cw; + word_cnt++; + + if (word_cnt == 1 && corrected_cw != POCSAG_SYNCCODE) { + got_SC = false; + bit_inverted = false; is_message_ready = true; - printf("Addr: %d | Numeric: %s | Alpha: %s\n", address, numeric_msg.c_str(), alpha_msg.c_str()); + // printf("Addr: %d | Numeric: %s | Alpha: %s\n", address, numeric_msg.c_str(), alpha_msg.c_str()); } - sync_cnt = SAMPLES_PER_SYMBOL; + if (word_cnt == PAGERDEMOD_BATCH_WORDS) { + decodeBatch(); + batch_num++; + word_cnt = 0; + } + + bits = 0; + bit_cnt = 0; + } + } prev_data = data; diff --git a/app/src/main/cpp/demod.h b/app/src/main/cpp/demod.h index 6c42aa8..453a728 100644 --- a/app/src/main/cpp/demod.h +++ b/app/src/main/cpp/demod.h @@ -6,10 +6,13 @@ #include #include #include +#include #include "dsp/phasediscri.h" #include "dsp/firfilter.h" #include "util/movingaverage.h" +#include "util/qtypes.h" +#include "dsp/decimatorsu.h" #define SDR_RX_SCALED 32768.0 #define SAMPLE_RATE 48000.0 @@ -24,14 +27,21 @@ #define PAGERDEMOD_CODEWORDS_PER_FRAME 2 extern bool is_message_ready; -extern std::string numeric_msg; -extern uint32_t address; + +struct pocsag_msg { + uint32_t i; + uint32_t addr; + uint16_t func; + std::string numeric; + std::string alpha; +}; +extern std::unique_ptr> msg; extern PhaseDiscriminators phaseDiscri; extern Lowpass lowpassBaud; extern MovingAverageUtil preambleMovingAverage; extern double magsqRaw; -void processOneSample(int8_t i, int8_t q); +void processOneSample(float i, float q); #endif \ No newline at end of file diff --git a/app/src/main/cpp/native-lib.cpp b/app/src/main/cpp/native-lib.cpp index c985aeb..5bfa079 100644 --- a/app/src/main/cpp/native-lib.cpp +++ b/app/src/main/cpp/native-lib.cpp @@ -62,40 +62,55 @@ void clientThread(std::string host, int port) { running = true; - const int DECIM = 5; - int decim_counter = 0; - uint32_t acc_i = 0, acc_q = 0; + // 改用SDRAngel的decimator函数 + DecimatorsU m_decimatorsIQ; + SampleVector m_convertBuffer(BUF_SIZE); + + // 信道滤波器 带宽12.5k + Lowpass channel_filter_i, channel_filter_q; + channel_filter_i.create( + 65, + SAMPLE_RATE, + 6250 + ); + channel_filter_q.create( + 65, + SAMPLE_RATE, + 6250 + ); while (running && (n = read(sockfd, buffer, BUF_SIZE)) > 0) { - for (int j = 0; j < n; j += 2) { - acc_i += buffer[j]; - acc_q += buffer[j + 1]; - if (++decim_counter == DECIM) { - int8_t i_ds = (int8_t)(((float) acc_i / DECIM) - 128); - int8_t q_ds = (int8_t)(((float) acc_q / DECIM) - 128); -// char buf[32]; -// sprintf(buf, "%d %d\n", i_ds, q_ds); -// std::ostringstream ss; -// ss << buf; -// { -// std::lock_guard lock(msgMutex); -// messageBuffer.push_back(ss.str()); -// } - processOneSample(i_ds, q_ds); - acc_i = acc_q = 0; - decim_counter = 0; - } + auto it = m_convertBuffer.begin(); + + // 1536ksps/32 = 48ksps,SUP情况下fc + 48k + // 固定采样率或许不是好主意,但现在就先这样了... + m_decimatorsIQ.decimate32_sup(&it, buffer, BUF_SIZE); + + // 这里有个FLL可能对于没有tcxo的rtlsdr会友好一些... + + for (auto p = m_convertBuffer.begin(); p != it; ++p) { + // 信道滤波 + auto i_ds = channel_filter_i.filter(p->real()); + auto q_ds = channel_filter_q.filter(p->imag()); + + // 类型转换 + // 这我也不知道该怎么归一化了...先写了个2048,貌似这个值不会让信号强度条溢出 + float fi = ((float) i_ds) / 2048.0f; + float fq = ((float) q_ds) / 2048.0f; + processOneSample(fi, fq); } if (is_message_ready) { - std::ostringstream ss; - char addr_buf[32]; - snprintf(addr_buf, sizeof(addr_buf), "%010d ", address); // 10 + 10位补零 - ss << "[MSG] " << addr_buf << numeric_msg; - { - std::lock_guard lock(msgMutex); - messageBuffer.push_back(ss.str()); + for (int i = 0; i < msg->size(); i++) { + std::ostringstream ss; + char addr_buf[32]; + snprintf(addr_buf, sizeof(addr_buf), "%010d ", msg->at(i).addr); // 10 + 10位补零 + ss << "[MSG] " << addr_buf << msg->at(i).numeric; + { + std::lock_guard lock(msgMutex); + messageBuffer.push_back(ss.str()); + } } is_message_ready = false; } diff --git a/app/src/main/cpp/util/qtypes.h b/app/src/main/cpp/util/qtypes.h new file mode 100644 index 0000000..37b445a --- /dev/null +++ b/app/src/main/cpp/util/qtypes.h @@ -0,0 +1,301 @@ +// 为了兼容性只能把这个复制过来了... +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTYPES_H +#define QTYPES_H + +// #include +// #include +// #include +// #include + +#ifdef __cplusplus +# include +# if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE == 0 +# error "Qt requires std::byte, but _HAS_STD_BYTE has been set to 0" +# endif +# include +# if defined(__STDCPP_FLOAT16_T__) && __has_include() +// P1467 implementation - https://wg21.link/p1467 +# include +# endif // defined(__STDCPP_FLOAT16_T__) && __has_include() +# include +#else +# include +#endif + +#if 0 +#pragma qt_class(QtTypes) +#pragma qt_class(QIntegerForSize) +#pragma qt_sync_stop_processing +#endif + +/* + Useful type definitions for Qt +*/ +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +// QT_BEGIN_NAMESPACE + +/* + Size-dependent types (architecture-dependent byte order) + + Make sure to update QMetaType when changing these typedefs +*/ + +typedef signed char qint8; /* 8 bit signed */ +typedef unsigned char quint8; /* 8 bit unsigned */ +typedef short qint16; /* 16 bit signed */ +typedef unsigned short quint16; /* 16 bit unsigned */ +typedef int qint32; /* 32 bit signed */ +typedef unsigned int quint32; /* 32 bit unsigned */ +// Unlike LL / ULL in C++, for historical reasons, we force the +// result to be of the requested type. +#ifdef __cplusplus +# define Q_INT64_C(c) static_cast(c ## LL) /* signed 64 bit constant */ +# define Q_UINT64_C(c) static_cast(c ## ULL) /* unsigned 64 bit constant */ +#else +# define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */ +# define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */ +#endif +typedef long long qint64; /* 64 bit signed */ +typedef unsigned long long quint64; /* 64 bit unsigned */ + +typedef qint64 qlonglong; +typedef quint64 qulonglong; + +#ifdef Q_QDOC // QDoc always needs to see the typedefs +# define QT_SUPPORTS_INT128 16 +#elif defined(QT_COMPILER_SUPPORTS_INT128) && !defined(QT_NO_INT128) +# define QT_SUPPORTS_INT128 QT_COMPILER_SUPPORTS_INT128 +# if defined(__GLIBCXX__) && defined(__STRICT_ANSI__) // -ansi/-std=c++NN instead of gnu++NN +# undef QT_SUPPORTS_INT128 // breaks on libstdc++ +# endif +# if defined(__clang__) && defined(_MSVC_STL_VERSION) // Clang with MSVC's STL +# undef QT_SUPPORTS_INT128 // MSVC's STL doesn't support int128 +# endif +#else +# undef QT_SUPPORTS_INT128 +#endif + +#if defined(QT_SUPPORTS_INT128) +__extension__ typedef __int128_t qint128; +__extension__ typedef __uint128_t quint128; + +#ifdef __cplusplus +static_assert(std::is_signed_v, + "Qt requires and to work for q(u)int128."); +#endif + +// limits: +# ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */ +# define QT_C_STYLE_CAST(type, x) static_cast(x) +# else /* but C doesn't have constructor-style casts */ +# define QT_C_STYLE_CAST(type, x) ((type)(x)) +# endif +# ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */ +# define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1) +# endif +# define Q_INT128_MAX QT_C_STYLE_CAST(qint128, Q_UINT128_MAX / 2) +# define Q_INT128_MIN (-Q_INT128_MAX - 1) + +# ifdef __cplusplus + namespace QtPrivate::NumberLiterals { + namespace detail { + template + constexpr quint128 construct() { return accu; } + + template + constexpr quint128 construct() + { + if constexpr (C != '\'') { // ignore digit separators + const int digitValue = '0' <= C && C <= '9' ? C - '0' : + 'a' <= C && C <= 'z' ? C - 'a' + 10 : + 'A' <= C && C <= 'Z' ? C - 'A' + 10 : + /* else */ -1 ; + static_assert(digitValue >= 0 && digitValue < base, + "Invalid character"); + // accu * base + digitValue <= MAX, but without overflow: + static_assert(accu <= (Q_UINT128_MAX - digitValue) / base, + "Overflow occurred"); + return construct(); + } else { + return construct(); + } + } + + template + constexpr quint128 parse0xb() + { + constexpr quint128 accu = 0; + if constexpr (C == 'x' || C == 'X') + return construct(); // base 16, skip 'x' + else if constexpr (C == 'b' || C == 'B') + return construct(); // base 2, skip 'b' + else + return construct(); // base 8, include C + } + + template + constexpr quint128 parse0() + { + if constexpr (sizeof...(Cs) == 0) // this was just a literal 0 + return 0; + else + return parse0xb(); + } + + template + constexpr quint128 parse() + { + if constexpr (C == '0') + return parse0(); // base 2, 8, or 16 (or just a literal 0), skip '0' + else + return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C + } + } // namespace detail + template + constexpr quint128 operator""_quint128() noexcept + { return QtPrivate::NumberLiterals::detail::parse(); } + template + constexpr qint128 operator""_qint128() noexcept + { return qint128(QtPrivate::NumberLiterals::detail::parse()); } + + #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override + # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }()) + #endif + #ifndef Q_INT128_C // allow qcompilerdetection.h/user override + # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }()) + #endif + + } // namespace QtPrivate::NumberLiterals +# endif // __cplusplus +#endif // QT_SUPPORTS_INT128 + +#ifndef __cplusplus +// In C++ mode, we define below using QIntegerForSize template +static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions"); +typedef ptrdiff_t qptrdiff; +typedef ptrdiff_t qsizetype; +typedef ptrdiff_t qintptr; +typedef size_t quintptr; + +#define PRIdQPTRDIFF "td" +#define PRIiQPTRDIFF "ti" + +#define PRIdQSIZETYPE "td" +#define PRIiQSIZETYPE "ti" + +#define PRIdQINTPTR "td" +#define PRIiQINTPTR "ti" + +#define PRIuQUINTPTR "zu" +#define PRIoQUINTPTR "zo" +#define PRIxQUINTPTR "zx" +#define PRIXQUINTPTR "zX" +#endif + +#if defined(QT_COORD_TYPE) +typedef QT_COORD_TYPE qreal; +#else +typedef double qreal; +#endif + +#if defined(__cplusplus) +/* + quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e. + + sizeof(void *) == sizeof(quintptr) + && sizeof(void *) == sizeof(qptrdiff) + + While size_t and qsizetype are not guaranteed to be the same size as a pointer, + they usually are and we do check for that in qtypes.cpp, just to be sure. +*/ +template struct QIntegerForSize; +template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; +template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; +template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; +template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; +#if defined(QT_SUPPORTS_INT128) +template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; }; +#endif +// template struct QIntegerForSizeof: QIntegerForSize { }; +// typedef QIntegerForSize::Signed qregisterint; +// typedef QIntegerForSize::Unsigned qregisteruint; +// typedef QIntegerForSizeof::Unsigned quintptr; +// typedef QIntegerForSizeof::Signed qptrdiff; +// typedef qptrdiff qintptr; +// using qsizetype = QIntegerForSizeof::Signed; + +// These custom definitions are necessary as we're not defining our +// datatypes in terms of the language ones, but in terms of integer +// types that have the sime size. For instance, on a 32-bit platform, +// qptrdiff is int, while ptrdiff_t may be aliased to long; therefore +// using %td to print a qptrdiff would be wrong (and raise -Wformat +// warnings), although both int and long have same bit size on that +// platform. +// +// We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). +#if SIZE_MAX == 0xffffffffULL +#define PRIuQUINTPTR "u" +#define PRIoQUINTPTR "o" +#define PRIxQUINTPTR "x" +#define PRIXQUINTPTR "X" + +#define PRIdQPTRDIFF "d" +#define PRIiQPTRDIFF "i" + +#define PRIdQINTPTR "d" +#define PRIiQINTPTR "i" + +#define PRIdQSIZETYPE "d" +#define PRIiQSIZETYPE "i" +#elif SIZE_MAX == 0xffffffffffffffffULL +#define PRIuQUINTPTR "llu" +#define PRIoQUINTPTR "llo" +#define PRIxQUINTPTR "llx" +#define PRIXQUINTPTR "llX" + +#define PRIdQPTRDIFF "lld" +#define PRIiQPTRDIFF "lli" + +#define PRIdQINTPTR "lld" +#define PRIiQINTPTR "lli" + +#define PRIdQSIZETYPE "lld" +#define PRIiQSIZETYPE "lli" +#else +#error Unsupported platform (unknown value for SIZE_MAX) +#endif + +// Define a native float16 type +namespace QtPrivate { +#if defined(__STDCPP_FLOAT16_T__) +# define QFLOAT16_IS_NATIVE 1 +using NativeFloat16Type = std::float16_t; +#elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0 +// disabled due to https://github.com/llvm/llvm-project/issues/56963 +# define QFLOAT16_IS_NATIVE 1 +using NativeFloat16Type = decltype(__FLT16_MAX__); +#elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__ARM_FP16_FORMAT_IEEE) +# define QFLOAT16_IS_NATIVE 1 +using NativeFloat16Type = __fp16; +#elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__SSE2__) +# define QFLOAT16_IS_NATIVE 1 +using NativeFloat16Type = _Float16; +#else +# define QFLOAT16_IS_NATIVE 0 +using NativeFloat16Type = void; +#endif +} // QtPrivate + +#endif // __cplusplus + +// QT_END_NAMESPACE + +#endif // QTYPES_H