diff --git a/pw_assert_tokenized/docs.rst b/pw_assert_tokenized/docs.rst index c423b1ee11..3530e44dda 100644 --- a/pw_assert_tokenized/docs.rst +++ b/pw_assert_tokenized/docs.rst @@ -49,10 +49,11 @@ Setup #. Set ``pw_assert_BACKEND = "$dir_pw_assert_tokenized:check_backend"`` and ``pw_assert_LITE_BACKEND = "$dir_pw_assert_tokenized:assert_backend"`` in your target configuration. -#. Ensure your target provides ``pw_tokenizer_GLOBAL_HANDLER_BACKEND``. By - default, pw_assert_tokenized will forward assert failures to the tokenizer - handler as logs. The tokenizer handler should check for ``LOG_LEVEL_FATAL`` - and properly divert to a crash handler. +#. Ensure your target provides + ``pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND``. By default, + pw_assert_tokenized will forward assert failures to the tokenizer handler as + logs. The tokenizer handler should check for ``LOG_LEVEL_FATAL`` and properly + divert to a crash handler. #. Add file name tokens to your token database. pw_assert_tokenized can't create file name tokens that can be parsed out of the final compiled binary. The ``pw_relative_source_file_names`` diff --git a/pw_tokenizer/BUILD.bazel b/pw_tokenizer/BUILD.bazel index 32d90e88c2..4f4fe922e0 100644 --- a/pw_tokenizer/BUILD.bazel +++ b/pw_tokenizer/BUILD.bazel @@ -62,16 +62,6 @@ pw_cc_library( visibility = ["@pigweed_config//:__pkg__"], ) -pw_cc_library( - name = "global_handler", - srcs = ["tokenize_to_global_handler.cc"], - hdrs = ["public/pw_tokenizer/tokenize_to_global_handler.h"], - deps = [ - ":pw_tokenizer", - "@pigweed_config//:pw_tokenizer_global_handler_backend", - ], -) - pw_cc_library( name = "global_handler_with_payload", srcs = ["tokenize_to_global_handler_with_payload.cc"], @@ -231,10 +221,7 @@ pw_cc_test( "global_handlers_test_c.c", "pw_tokenizer_private/tokenize_test.h", ], - deps = [ - ":global_handler", - ":global_handler_with_payload", - ], + deps = [":global_handler_with_payload"], ) pw_cc_test( @@ -256,7 +243,6 @@ pw_cc_test( "simple_tokenize_test.cc", ], deps = [ - ":global_handler", ":global_handler_with_payload", ":pw_tokenizer", "//pw_unit_test", diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn index 46b624b83f..3d279e02ee 100644 --- a/pw_tokenizer/BUILD.gn +++ b/pw_tokenizer/BUILD.gn @@ -105,15 +105,13 @@ pw_source_set("pw_tokenizer") { # As a temporary workaround, if no backend is set, use an empty test backend so # that the test can define the handler function. # TODO(hepler): Switch this to a facade test when available. -if (pw_tokenizer_GLOBAL_HANDLER_BACKEND == "" && - pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND == "") { +if (pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND == "") { # This is an empty library to use as the backend for global_handler and # global_handler_with_payload tests. pw_source_set("test_backend") { visibility = [ ":*" ] } - pw_tokenizer_GLOBAL_HANDLER_BACKEND = ":test_backend" pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND = ":test_backend" enable_global_handler_test = true @@ -121,15 +119,6 @@ if (pw_tokenizer_GLOBAL_HANDLER_BACKEND == "" && enable_global_handler_test = false } -pw_facade("global_handler") { - backend = pw_tokenizer_GLOBAL_HANDLER_BACKEND - - public_configs = [ ":public_include_path" ] - public = [ "public/pw_tokenizer/tokenize_to_global_handler.h" ] - sources = [ "tokenize_to_global_handler.cc" ] - public_deps = [ ":pw_tokenizer" ] -} - pw_facade("global_handler_with_payload") { backend = pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND @@ -263,10 +252,7 @@ pw_test("global_handlers_test") { "global_handlers_test_c.c", "pw_tokenizer_private/tokenize_test.h", ] - deps = [ - ":global_handler", - ":global_handler_with_payload", - ] + deps = [ ":global_handler_with_payload" ] # TODO(hepler): Switch this to a facade test when available. enable_if = enable_global_handler_test @@ -283,7 +269,6 @@ pw_test("hash_test") { pw_test("simple_tokenize_test") { sources = [ "simple_tokenize_test.cc" ] deps = [ - ":global_handler", ":global_handler_with_payload", ":pw_tokenizer", ] diff --git a/pw_tokenizer/CMakeLists.txt b/pw_tokenizer/CMakeLists.txt index 4fbf6442ba..f60729cd64 100644 --- a/pw_tokenizer/CMakeLists.txt +++ b/pw_tokenizer/CMakeLists.txt @@ -103,20 +103,6 @@ pw_add_library(pw_tokenizer.decoder STATIC pw_varint ) -pw_add_facade(pw_tokenizer.global_handler STATIC - BACKEND - pw_tokenizer.global_handler_BACKEND - HEADERS - public/pw_tokenizer/tokenize_to_global_handler.h - PUBLIC_INCLUDES - public - PUBLIC_DEPS - pw_preprocessor - pw_tokenizer - SOURCES - tokenize_to_global_handler.cc -) - pw_add_facade(pw_tokenizer.global_handler_with_payload STATIC BACKEND pw_tokenizer.global_handler_with_payload_BACKEND diff --git a/pw_tokenizer/backend.cmake b/pw_tokenizer/backend.cmake index 1890f392d9..997b18ecb0 100644 --- a/pw_tokenizer/backend.cmake +++ b/pw_tokenizer/backend.cmake @@ -15,7 +15,5 @@ include_guard(GLOBAL) include($ENV{PW_ROOT}/pw_build/pigweed.cmake) -# Backends for the pw_tokenizer:global_handler and -# pw_tokenizer:global_handler_with_payload facades -pw_add_backend_variable(pw_tokenizer.global_handler_BACKEND) +# Backend for the pw_tokenizer:global_handler_with_payload facade. pw_add_backend_variable(pw_tokenizer.global_handler_with_payload_BACKEND) diff --git a/pw_tokenizer/backend.gni b/pw_tokenizer/backend.gni index dd00ac93bf..9f01212aba 100644 --- a/pw_tokenizer/backend.gni +++ b/pw_tokenizer/backend.gni @@ -13,8 +13,6 @@ # the License. declare_args() { - # Backends for the pw_tokenizer:global_handler and - # pw_tokenizer:global_handler_with_payload facades. - pw_tokenizer_GLOBAL_HANDLER_BACKEND = "" + # Backend for the pw_tokenizer:global_handler_with_payload facade. pw_tokenizer_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND = "" } diff --git a/pw_tokenizer/docs.rst b/pw_tokenizer/docs.rst index 6c16979e02..47cbf16b7b 100644 --- a/pw_tokenizer/docs.rst +++ b/pw_tokenizer/docs.rst @@ -168,106 +168,123 @@ Adding tokenization to a project is simple. To tokenize a string, include Tokenize a string literal ------------------------- -The ``PW_TOKENIZE_STRING`` macro converts a string literal to a ``uint32_t`` -token. +``pw_tokenizer`` provides macros for tokenizing string literals with no +arguments. -.. code-block:: cpp +.. c:macro:: PW_TOKENIZE_STRING(string_literal) - constexpr uint32_t token = PW_TOKENIZE_STRING("Any string literal!"); + Converts a string literal to a ``uint32_t`` token in a standalone statement. + C and C++ compatible. -.. admonition:: When to use this macro + .. code-block:: cpp - Use ``PW_TOKENIZE_STRING`` to tokenize string literals that do not have - %-style arguments. + constexpr uint32_t token = PW_TOKENIZE_STRING("Any string literal!"); -Tokenize to a handler function ------------------------------- -``PW_TOKENIZE_TO_GLOBAL_HANDLER`` is the most efficient tokenization function, -since it takes the fewest arguments. It encodes a tokenized string to a -buffer on the stack. The size of the buffer is set with -``PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES``. +.. c:macro:: PW_TOKENIZE_STRING_DOMAIN(domain, string_literal) -This macro is provided by the ``pw_tokenizer:global_handler`` facade. The -backend for this facade must define the ``pw_tokenizer_HandleEncodedMessage`` -C-linkage function. + Tokenizes a string literal in a standalone statement using the specified + :ref:`domain `. C and C++ compatible. -.. code-block:: cpp +.. c:macro:: PW_TOKENIZE_STRING_MASK(domain, mask, string_literal) - PW_TOKENIZE_TO_GLOBAL_HANDLER(format_string_literal, arguments...); + Tokenizes a string literal in a standalone stateemnt using the specified + :ref:`domain ` and :ref:`bit mask + `. C and C++ compatible. - void pw_tokenizer_HandleEncodedMessage(const uint8_t encoded_message[], - size_t size_bytes); +The tokenization macros above cannot be used inside other expressions. -``PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD`` is similar, but passes a -``uintptr_t`` argument to the global handler function. Values like a log level -can be packed into the ``uintptr_t``. +.. admonition:: **Yes**: Assign :c:macro:`PW_TOKENIZE_STRING` to a ``constexpr`` variable. + :class: checkmark -This macro is provided by the ``pw_tokenizer:global_handler_with_payload`` -facade. The backend for this facade must define the -``pw_tokenizer_HandleEncodedMessageWithPayload`` C-linkage function. + .. code:: cpp -.. code-block:: cpp + constexpr uint32_t kGlobalToken = PW_TOKENIZE_STRING("Wowee Zowee!"); - PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(payload, - format_string_literal, - arguments...); + void Function() { + constexpr uint32_t local_token = PW_TOKENIZE_STRING("Wowee Zowee?"); + } - void pw_tokenizer_HandleEncodedMessageWithPayload( - uintptr_t payload, const uint8_t encoded_message[], size_t size_bytes); +.. admonition:: **No**: Use :c:macro:`PW_TOKENIZE_STRING` in another expression. + :class: error + + .. code:: cpp + + void BadExample() { + ProcessToken(PW_TOKENIZE_STRING("This won't compile!")); + } + + Use :c:macro:`PW_TOKENIZE_STRING_EXPR` instead. + +An alternate set of macros are provided for use inside expressions. These make +use of lambda functions, so while they can be used inside expressions, they +require C++ and cannot be assigned to constexpr variables or be used with +special function variables like ``__func__``. + +.. c:macro:: PW_TOKENIZE_STRING_EXPR(string_literal) + + Converts a string literal to a ``uint32_t`` token within an expression. + Requires C++. + + .. code-block:: cpp + + DoSomething(PW_TOKENIZE_STRING_EXPR("Succeed")); + +.. c:macro:: PW_TOKENIZE_STRING_DOMAIN_EXPR(domain, string_literal) + + Tokenizes a string literal using the specified :ref:`domain + ` within an expression. Requires C++. + +.. c:macro:: PW_TOKENIZE_STRING_MASK_EXPR(domain, mask, string_literal) + + Tokenizes a string literal using the specified :ref:`domain + ` and :ref:`bit mask + ` within an expression. Requires C++. .. admonition:: When to use these macros - Use anytime a global handler is sufficient, particularly for widely expanded - macros, like a logging macro. ``PW_TOKENIZE_TO_GLOBAL_HANDLER`` or - ``PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD`` are the most efficient macros - for tokenizing printf-style strings. + Use :c:macro:`PW_TOKENIZE_STRING` and related macros to tokenize string + literals that do not need %-style arguments encoded. -Tokenize to a callback ----------------------- -``PW_TOKENIZE_TO_CALLBACK`` tokenizes to a buffer on the stack and calls a -``void(const uint8_t* buffer, size_t buffer_size)`` callback that is provided at -the call site. The size of the buffer is set with -``PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES``. +.. admonition:: **Yes**: Use :c:macro:`PW_TOKENIZE_STRING_EXPR` within other expressions. + :class: checkmark -.. code-block:: cpp + .. code:: cpp - PW_TOKENIZE_TO_CALLBACK(HandlerFunction, "Format string: %x", arguments...); + void GoodExample() { + ProcessToken(PW_TOKENIZE_STRING_EXPR("This will compile!")); + } -.. admonition:: When to use this macro +.. admonition:: **No**: Assign :c:macro:`PW_TOKENIZE_STRING_EXPR` to a ``constexpr`` variable. + :class: error - Use ``PW_TOKENIZE_TO_CALLBACK`` if the global handler version is already in - use for another purpose or more flexibility is needed. + .. code:: cpp -Tokenize to a buffer --------------------- -The most flexible tokenization macro is ``PW_TOKENIZE_TO_BUFFER``, which encodes -to a caller-provided buffer. + constexpr uint32_t wont_work = PW_TOKENIZE_STRING_EXPR("This won't compile!")); -.. code-block:: cpp + Instead, use :c:macro:`PW_TOKENIZE_STRING` to assign to a ``constexpr`` variable. - uint8_t buffer[BUFFER_SIZE]; - size_t size_bytes = sizeof(buffer); - PW_TOKENIZE_TO_BUFFER(buffer, &size_bytes, format_string_literal, arguments...); +.. admonition:: **No**: Tokenize ``__func__`` in :c:macro:`PW_TOKENIZE_STRING_EXPR`. + :class: error -While ``PW_TOKENIZE_TO_BUFFER`` is maximally flexible, it takes more arguments -than the other macros, so its per-use code size overhead is larger. + .. code:: cpp -.. admonition:: When to use this macro + void BadExample() { + // This compiles, but __func__ will not be the outer function's name, and + // there may be compiler warnings. + constexpr uint32_t wont_work = PW_TOKENIZE_STRING_EXPR(__func__); + } - Use ``PW_TOKENIZE_TO_BUFFER`` to encode to a custom-sized buffer or if the - other macros are insufficient. Avoid using ``PW_TOKENIZE_TO_BUFFER`` in - widely expanded macros, such as a logging macro, because it will result in - larger code size than its alternatives. + Instead, use :c:macro:`PW_TOKENIZE_STRING` to tokenize ``__func__`` or similar macros. .. _module-pw_tokenizer-custom-macro: -Tokenize with a custom macro ----------------------------- -Projects may need more flexbility than the standard ``pw_tokenizer`` macros -provide. To support this, projects may define custom tokenization macros. This -requires the use of two low-level ``pw_tokenizer`` macros: +Tokenize a message with arguments in a custom macro +--------------------------------------------------- +Projects can leverage the tokenization machinery in whichever way best suits +their needs. ``pw_tokenizer`` provides two low-level macros for projects to use +to create custom tokenization macros. -.. c:macro:: PW_TOKENIZE_FORMAT_STRING(domain, mask, format, ...) +.. c:macro:: PW_TOKENIZE_FORMAT_STRING(domain, mask, format_string, ...) Tokenizes a format string and sets the ``_pw_tokenizer_token`` variable to the token. Must be used in its own scope, since the same variable is used in every @@ -282,9 +299,10 @@ requires the use of two low-level ``pw_tokenizer`` macros: Converts a series of arguments to a compact format that replaces the format string literal. -Use these two macros within the custom tokenization macro to call a function -that does the encoding. The following example implements a custom tokenization -macro for use with :ref:`module-pw_log_tokenized`. +The most efficient way to use ``pw_tokenizer`` is to pass tokenized data to a +global handler function. A project's custom tokenization macro can handle +tokenized data in a function of their choosing. The following example implements +a custom tokenization macro for use with :ref:`module-pw_log_tokenized`. .. code-block:: cpp @@ -339,14 +357,66 @@ transmitted or stored as needed. HandleTokenizedMessage(metadata, encoded_message); } -.. admonition:: When to use a custom macro +.. admonition:: Why use a custom macro + + - Optimal code size. Invoking a free function with the tokenized data results + in the smallest possible call site. + - Pass additional arguments, such as metadata, with the tokenized message. + - Integrate ``pw_tokenizer`` with other systems. + +Tokenize a message with arguments to a buffer +--------------------------------------------- +.. c:macro:: PW_TOKENIZE_TO_BUFFER(buffer_pointer, buffer_size_pointer, format_string, arguments...) + + ``PW_TOKENIZE_TO_BUFFER`` encodes to a caller-provided buffer. + + .. code-block:: cpp - Use existing tokenization macros whenever possible. A custom macro may be - needed to support use cases like the following: + uint8_t buffer[BUFFER_SIZE]; + size_t size_bytes = sizeof(buffer); + PW_TOKENIZE_TO_BUFFER(buffer, &size_bytes, format_string_literal, arguments...); - * Variations of ``PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD`` that take - different arguments. - * Supporting global handler macros that use different handler functions. + While ``PW_TOKENIZE_TO_BUFFER`` is very flexible, it must be passed a buffer, + which increases its call site overhead. + +.. admonition:: Why use this macro + + - Encode a tokenized message for consumption within a function. + - Encode a tokenized message into an existing buffer. + + Avoid using ``PW_TOKENIZE_TO_BUFFER`` in widely expanded macros, such as a + logging macro, because it will result in larger code size than passing the + tokenized data to a function. + +Tokenize to a global handler function (deprecated) +-------------------------------------------------- +``pw_tokenizer`` provides the ``PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD`` +macro that tokenizes to a global handler function. This macro is deprecated and +should not be used in new code. Create a :ref:`custom macro +` instead. + +``PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD`` passes a ``uintptr_t`` argument +along with the tokenized data. Values like a log level can be packed into the +``uintptr_t``. The tokenized string is encoded to a buffer on the stack. The +size of the buffer is set with ``PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES``. + +This macro is provided by the ``pw_tokenizer:global_handler_with_payload`` +facade. The backend for this facade must define the +``pw_tokenizer_HandleEncodedMessageWithPayload`` C-linkage function. + +.. code-block:: cpp + + PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(payload, + format_string_literal, + arguments...); + + void pw_tokenizer_HandleEncodedMessageWithPayload( + uintptr_t payload, const uint8_t encoded_message[], size_t size_bytes); + +.. admonition:: Why use this macro + + This macro is deprecated and should not be used. To invoke a global function, + create a :ref:`custom tokenization macro`. Binary logging with pw_tokenizer ================================ @@ -552,6 +622,8 @@ example, the following reads strings in ``some_domain`` from ``my_image.elf``. See `Managing token databases`_ for information about the ``database.py`` command line tool. +.. _module-pw_tokenizer-masks: + Smaller tokens with masking =========================== ``pw_tokenizer`` uses 32-bit tokens. On 32-bit or 64-bit architectures, using @@ -652,32 +724,6 @@ masking`_). 16 bits might be acceptable when tokenizing a small set of strings, such as module names, but won't be suitable for large sets of strings, like log messages. -Using tokenization in expressions -================================= -The tokenization macros above cannot be used inside expressions. For example, -the following code snippet will fail to compile: - -.. code-block:: cpp - - DoSomething(PW_TOKENIZE_STRING("Fail")); - -An alternate set of macros are provided for use inside expressions. These make -use of lambda functions, so while they can be used inside expressions, they -cannot be assigned to constexpr variables or be used with special function -variables like ``__func__``. - -The following tokenization macros may be used inside epxressions: - -* ``PW_TOKENIZE_STRING_EXPR`` -* ``PW_TOKENIZE_STRING_DOMAIN_EXPR`` -* ``PW_TOKENIZE_STRING_MASK_EXPR`` - -For example, the following code snippet will work: - -.. code-block:: cpp - - DoSomething(PW_TOKENIZE_STRING_EXPR("Succeed")); - --------------- Token databases --------------- @@ -1416,7 +1462,9 @@ Firmware deployment ``pw_tokenizer_HandleEncodedMessageWithPayload``, the log messages were encoded in the $-prefixed `Base64 format`_, then dispatched as normal log messages. -* Asserts were tokenized using ``PW_TOKENIZE_TO_CALLBACK``. +* Asserts were tokenized a callback-based API that has been removed (a + :ref:`custom macro ` is a better + alternative). .. attention:: Do not encode line numbers in tokenized strings. This results in a huge diff --git a/pw_tokenizer/global_handlers_test.cc b/pw_tokenizer/global_handlers_test.cc index bef914e656..b79dab8e00 100644 --- a/pw_tokenizer/global_handlers_test.cc +++ b/pw_tokenizer/global_handlers_test.cc @@ -17,7 +17,6 @@ #include #include "gtest/gtest.h" -#include "pw_tokenizer/tokenize_to_global_handler.h" #include "pw_tokenizer/tokenize_to_global_handler_with_payload.h" #include "pw_tokenizer_private/tokenize_test.h" @@ -65,58 +64,6 @@ uint8_t GlobalMessage::message_[256] = {}; template size_t GlobalMessage::message_size_bytes_ = 0; -class TokenizeToGlobalHandler : public GlobalMessage { -}; - -TEST_F(TokenizeToGlobalHandler, Variety) { - PW_TOKENIZE_TO_GLOBAL_HANDLER("%x%lld%1.2f%s", 0, 0ll, -0.0, ""); - const auto expected = - ExpectedData<0, 0, 0x00, 0x00, 0x00, 0x80, 0>("%x%lld%1.2f%s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToGlobalHandler, Strings) { - PW_TOKENIZE_TO_GLOBAL_HANDLER("The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToGlobalHandler, Domain_Strings) { - PW_TOKENIZE_TO_GLOBAL_HANDLER_DOMAIN( - "TEST_DOMAIN", "The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToGlobalHandler, Mask) { - PW_TOKENIZE_TO_GLOBAL_HANDLER_MASK( - "TEST_DOMAIN", 0x00FFF000, "The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s", 0x00FFF000); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToGlobalHandler, C_SequentialZigZag) { - pw_tokenizer_ToGlobalHandlerTest_SequentialZigZag(); - - constexpr std::array expected = - ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>( - TEST_FORMAT_SEQUENTIAL_ZIG_ZAG); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -extern "C" void pw_tokenizer_HandleEncodedMessage( - const uint8_t* encoded_message, size_t size_bytes) { - TokenizeToGlobalHandler::SetMessage(encoded_message, size_bytes); -} - class TokenizeToGlobalHandlerWithPayload : public GlobalMessage { public: @@ -253,26 +200,6 @@ extern "C" void pw_tokenizer_HandleEncodedMessageWithPayload( tokenizer_domain = domain; \ string_literal = string -TEST_F(TokenizeToGlobalHandler, Domain_Default) { - const char* tokenizer_domain = nullptr; - const char* string_literal = nullptr; - - PW_TOKENIZE_TO_GLOBAL_HANDLER("404"); - - EXPECT_STREQ(tokenizer_domain, PW_TOKENIZER_DEFAULT_DOMAIN); - EXPECT_STREQ(string_literal, "404"); -} - -TEST_F(TokenizeToGlobalHandler, Domain_Specified) { - const char* tokenizer_domain = nullptr; - const char* string_literal = nullptr; - - PW_TOKENIZE_TO_GLOBAL_HANDLER_DOMAIN("www.google.com", "404"); - - EXPECT_STREQ(tokenizer_domain, "www.google.com"); - EXPECT_STREQ(string_literal, "404"); -} - TEST_F(TokenizeToGlobalHandlerWithPayload, Domain_Default) { const char* tokenizer_domain = nullptr; const char* string_literal = nullptr; diff --git a/pw_tokenizer/global_handlers_test_c.c b/pw_tokenizer/global_handlers_test_c.c index 04d555171e..fd8957b3b8 100644 --- a/pw_tokenizer/global_handlers_test_c.c +++ b/pw_tokenizer/global_handlers_test_c.c @@ -15,7 +15,6 @@ // This function tests the C implementation of tokenization API. These functions // are called from the main C++ test file. -#include "pw_tokenizer/tokenize_to_global_handler.h" #include "pw_tokenizer/tokenize_to_global_handler_with_payload.h" #include "pw_tokenizer_private/tokenize_test.h" @@ -26,23 +25,6 @@ // This test invokes the tokenization API with a variety of types. To simplify // validating the encoded data, numbers that are sequential when zig-zag encoded // are used as arguments. -void pw_tokenizer_ToGlobalHandlerTest_SequentialZigZag(void) { - PW_TOKENIZE_TO_GLOBAL_HANDLER(TEST_FORMAT_SEQUENTIAL_ZIG_ZAG, - 0u, - -1, - 1u, - (unsigned)-2, - (unsigned short)2u, - (signed char)-3, - 3, - -4l, - 4ul, - -5ll, - 5ull, - (signed char)-6, - (char)6, - (signed char)-7); -} void pw_tokenizer_ToGlobalHandlerWithPayloadTest_SequentialZigZag(void) { PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD((pw_tokenizer_Payload)600613, diff --git a/pw_tokenizer/public/pw_tokenizer/tokenize.h b/pw_tokenizer/public/pw_tokenizer/tokenize.h index 5f8cefa58f..fd9671516d 100644 --- a/pw_tokenizer/public/pw_tokenizer/tokenize.h +++ b/pw_tokenizer/public/pw_tokenizer/tokenize.h @@ -157,53 +157,6 @@ typedef uint32_t pw_tokenizer_Token; PW_COMMA_ARGS(__VA_ARGS__)); \ } while (0) -// Encodes a tokenized string and arguments to a buffer on the stack. The -// provided callback is called with the encoded data. The size of the -// stack-allocated argument encoding buffer is set with the -// PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES option. -// -// The macro's arguments are equivalent to the following function signature: -// -// TokenizeToCallback(void (*callback)(const uint8_t* data, size_t size), -// const char* format, -// ...); /* printf-style arguments */ -// -// For example, the following encodes a tokenized string with a sensor name and -// floating point data. The encoded message is passed directly to the -// MyProject_EnqueueMessageForUart function, which the caller provides as a -// callback. -// -// void MyProject_EnqueueMessageForUart(const uint8_t* buffer, -// size_t size_bytes) { -// uart_queue_write(uart_instance, buffer, size_bytes); -// } -// -// void LogSensorValue(const char* sensor_name, float value) { -// PW_TOKENIZE_TO_CALLBACK(MyProject_EnqueueMessageForUart, -// "%s: %f", -// sensor_name, -// value); -// } -// -#define PW_TOKENIZE_TO_CALLBACK(callback, format, ...) \ - PW_TOKENIZE_TO_CALLBACK_DOMAIN( \ - PW_TOKENIZER_DEFAULT_DOMAIN, callback, format, __VA_ARGS__) - -// Same as PW_TOKENIZE_TO_CALLBACK, but tokenizes to the specified domain. -#define PW_TOKENIZE_TO_CALLBACK_DOMAIN(domain, callback, format, ...) \ - PW_TOKENIZE_TO_CALLBACK_MASK( \ - domain, UINT32_MAX, callback, format, __VA_ARGS__) - -// Same as PW_TOKENIZE_TO_CALLBACK_DOMAIN, but applies a mask to the token. -#define PW_TOKENIZE_TO_CALLBACK_MASK(domain, mask, callback, format, ...) \ - do { \ - PW_TOKENIZE_FORMAT_STRING(domain, mask, format, __VA_ARGS__); \ - _pw_tokenizer_ToCallback(callback, \ - _pw_tokenizer_token, \ - PW_TOKENIZER_ARG_TYPES(__VA_ARGS__) \ - PW_COMMA_ARGS(__VA_ARGS__)); \ - } while (0) - PW_EXTERN_C_START // These functions encode the tokenized strings. These should not be called @@ -214,12 +167,6 @@ void _pw_tokenizer_ToBuffer(void* buffer, pw_tokenizer_ArgTypes types, ...); -void _pw_tokenizer_ToCallback(void (*callback)(const uint8_t* encoded_message, - size_t size_bytes), - pw_tokenizer_Token token, - pw_tokenizer_ArgTypes types, - ...); - // This empty function allows the compiler to check the format string. static inline void pw_tokenizer_CheckFormatString(const char* format, ...) PW_PRINTF_FORMAT(1, 2); diff --git a/pw_tokenizer/public/pw_tokenizer/tokenize_to_global_handler.h b/pw_tokenizer/public/pw_tokenizer/tokenize_to_global_handler.h deleted file mode 100644 index ca7e0b9463..0000000000 --- a/pw_tokenizer/public/pw_tokenizer/tokenize_to_global_handler.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -#pragma once - -#include -#include - -#include "pw_preprocessor/util.h" -#include "pw_tokenizer/tokenize.h" - -// Encodes a tokenized string and arguments to a buffer on the stack. The buffer -// is passed to the user-defined pw_tokenizer_HandleEncodedMessage function. The -// size of the stack-allocated argument encoding buffer is set with the -// PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES option. -// -// The macro's arguments are equivalent to the following function signature: -// -// TokenizeToGlobalHandler(const char* format, -// ...); /* printf-style arguments */ -// -// For example, the following encodes a tokenized string with a value returned -// from a function call. The encoded message is passed to the caller-defined -// pw_tokenizer_HandleEncodedMessage function. -// -// void OutputLastReadSize() { -// PW_TOKENIZE_TO_GLOBAL_HANDLER("Read %u bytes", ReadSizeBytes()); -// } -// -// void pw_tokenizer_HandleEncodedMessage(const uint8_t encoded_message[], -// size_t size_bytes) { -// MyProject_EnqueueMessageForUart(buffer, size_bytes); -// } -// -#define PW_TOKENIZE_TO_GLOBAL_HANDLER(format, ...) \ - PW_TOKENIZE_TO_GLOBAL_HANDLER_DOMAIN( \ - PW_TOKENIZER_DEFAULT_DOMAIN, format, __VA_ARGS__) - -// Same as PW_TOKENIZE_TO_GLOBAL_HANDLER, but tokenizes to the specified domain. -#define PW_TOKENIZE_TO_GLOBAL_HANDLER_DOMAIN(domain, format, ...) \ - PW_TOKENIZE_TO_GLOBAL_HANDLER_MASK(domain, UINT32_MAX, format, __VA_ARGS__) - -// Same as PW_TOKENIZE_TO_GLOBAL_HANDLER_DOMAIN, but applies a mask to the -// token. -#define PW_TOKENIZE_TO_GLOBAL_HANDLER_MASK(domain, mask, format, ...) \ - do { \ - PW_TOKENIZE_FORMAT_STRING(domain, mask, format, __VA_ARGS__); \ - _pw_tokenizer_ToGlobalHandler(_pw_tokenizer_token, \ - PW_TOKENIZER_ARG_TYPES(__VA_ARGS__) \ - PW_COMMA_ARGS(__VA_ARGS__)); \ - } while (0) - -PW_EXTERN_C_START - -// This function must be defined by the pw_tokenizer:global_handler backend. -// This function is called with the encoded message by -// _pw_tokenizer_ToGlobalHandler. -void pw_tokenizer_HandleEncodedMessage(const uint8_t encoded_message[], - size_t size_bytes); - -// This function encodes the tokenized strings. Do not call it directly; -// instead, use the PW_TOKENIZE_TO_GLOBAL_HANDLER macro. -void _pw_tokenizer_ToGlobalHandler(pw_tokenizer_Token token, - pw_tokenizer_ArgTypes types, - ...); - -PW_EXTERN_C_END diff --git a/pw_tokenizer/pw_tokenizer_private/tokenize_test.h b/pw_tokenizer/pw_tokenizer_private/tokenize_test.h index 3c4b4633fb..49e4bad05a 100644 --- a/pw_tokenizer/pw_tokenizer_private/tokenize_test.h +++ b/pw_tokenizer/pw_tokenizer_private/tokenize_test.h @@ -40,8 +40,6 @@ void pw_tokenizer_ToCallbackTest_SequentialZigZag( void pw_tokenizer_ToBufferTest_Requires8(void* buffer, size_t* buffer_size); -void pw_tokenizer_ToGlobalHandlerTest_SequentialZigZag(void); - void pw_tokenizer_ToGlobalHandlerWithPayloadTest_SequentialZigZag(void); PW_EXTERN_C_END diff --git a/pw_tokenizer/simple_tokenize_test.cc b/pw_tokenizer/simple_tokenize_test.cc index 00bf817f86..8733a62e48 100644 --- a/pw_tokenizer/simple_tokenize_test.cc +++ b/pw_tokenizer/simple_tokenize_test.cc @@ -18,7 +18,6 @@ #include "gtest/gtest.h" #include "pw_tokenizer/tokenize.h" -#include "pw_tokenizer/tokenize_to_global_handler.h" #include "pw_tokenizer/tokenize_to_global_handler_with_payload.h" namespace pw { @@ -101,8 +100,6 @@ uint8_t GlobalMessage::message_[256] = {}; template size_t GlobalMessage::message_size_bytes_ = 0; -class TokenizeToCallback : public GlobalMessage {}; - template std::array ExpectedData( const char (&format)[kSize]) { @@ -115,36 +112,6 @@ std::array ExpectedData( kData...}; } -TEST_F(TokenizeToCallback, Variety) { - PW_TOKENIZE_TO_CALLBACK( - SetMessage, "%s there are %x (%.2f) of them%c", "Now", 2u, 2.0f, '.'); - const auto expected = // clang-format off - ExpectedData<3, 'N', 'o', 'w', // string "Now" - 0x04, // unsigned 2 (zig-zag encoded) - 0x00, 0x00, 0x00, 0x40, // float 2.0 - 0x5C // char '.' (0x2E, zig-zag encoded) - >("%s there are %x (%.2f) of them%c"); - // clang-format on - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -class TokenizeToGlobalHandler : public GlobalMessage { -}; - -TEST_F(TokenizeToGlobalHandler, Variety) { - PW_TOKENIZE_TO_GLOBAL_HANDLER("%x%lld%1.2f%s", 0, 0ll, -0.0, ""); - const auto expected = - ExpectedData<0, 0, 0x00, 0x00, 0x00, 0x80, 0>("%x%lld%1.2f%s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -extern "C" void pw_tokenizer_HandleEncodedMessage( - const uint8_t* encoded_message, size_t size_bytes) { - TokenizeToGlobalHandler::SetMessage(encoded_message, size_bytes); -} - class TokenizeToGlobalHandlerWithPayload : public GlobalMessage { public: diff --git a/pw_tokenizer/tokenize.cc b/pw_tokenizer/tokenize.cc index 5206fcd944..5bed3fce6f 100644 --- a/pw_tokenizer/tokenize.cc +++ b/pw_tokenizer/tokenize.cc @@ -87,18 +87,5 @@ extern "C" void _pw_tokenizer_ToBuffer(void* buffer, *buffer_size_bytes = sizeof(token) + encoded_bytes; } -extern "C" void _pw_tokenizer_ToCallback( - void (*callback)(const uint8_t* encoded_message, size_t size_bytes), - Token token, - pw_tokenizer_ArgTypes types, - ...) { - va_list args; - va_start(args, types); - EncodedMessage encoded(token, types, args); - va_end(args); - - callback(encoded.data_as_uint8(), encoded.size()); -} - } // namespace tokenizer } // namespace pw diff --git a/pw_tokenizer/tokenize_test.cc b/pw_tokenizer/tokenize_test.cc index 0a1837f950..8efbba4464 100644 --- a/pw_tokenizer/tokenize_test.cc +++ b/pw_tokenizer/tokenize_test.cc @@ -540,91 +540,6 @@ TEST_F(TokenizeToBuffer, AsArgumentToAnotherMacro) { EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0); } -class TokenizeToCallback : public ::testing::Test { - public: - static void SetMessage(const uint8_t* message, size_t size) { - ASSERT_LE(size, sizeof(message_)); - std::memcpy(message_, message, size); - message_size_bytes_ = size; - } - - protected: - TokenizeToCallback() { - std::memset(message_, 0, sizeof(message_)); - message_size_bytes_ = 0; - } - - static uint8_t message_[256]; - static size_t message_size_bytes_; -}; - -uint8_t TokenizeToCallback::message_[256] = {}; -size_t TokenizeToCallback::message_size_bytes_ = 0; - -TEST_F(TokenizeToCallback, Variety) { - PW_TOKENIZE_TO_CALLBACK( - SetMessage, "%s there are %x (%.2f) of them%c", "Now", 2u, 2.0f, '.'); - const auto expected = // clang-format off - ExpectedData<3, 'N', 'o', 'w', // string "Now" - 0x04, // unsigned 2 (zig-zag encoded) - 0x00, 0x00, 0x00, 0x40, // float 2.0 - 0x5C // char '.' (0x2E, zig-zag encoded) - >("%s there are %x (%.2f) of them%c"); - // clang-format on - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, Strings) { - PW_TOKENIZE_TO_CALLBACK(SetMessage, "The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, Domain_Strings) { - PW_TOKENIZE_TO_CALLBACK_DOMAIN( - "TEST_DOMAIN", SetMessage, "The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s"); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, Mask) { - PW_TOKENIZE_TO_CALLBACK_MASK( - "TEST_DOMAIN", 0x00000FFF, SetMessage, "The answer is: %s", "5432!"); - constexpr std::array expected = - ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s", 0x00000FFF); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, CharArray) { - PW_TOKENIZE_TO_CALLBACK(SetMessage, __func__); - constexpr auto expected = ExpectedData(__func__); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, C_SequentialZigZag) { - pw_tokenizer_ToCallbackTest_SequentialZigZag(SetMessage); - - constexpr std::array expected = - ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>( - TEST_FORMAT_SEQUENTIAL_ZIG_ZAG); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - -TEST_F(TokenizeToCallback, AsArgumentToAnotherMacro) { - MACRO_THAT_CALLS_ANOTHER_MACRO(PW_TOKENIZE_TO_CALLBACK(SetMessage, __func__)); - constexpr auto expected = ExpectedData(__func__); - ASSERT_EQ(expected.size(), message_size_bytes_); - EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0); -} - #undef MACRO_THAT_CALLS_ANOTHER_MACRO #undef ANOTHER_MACRO @@ -659,26 +574,5 @@ TEST_F(TokenizeToBuffer, Domain_Specified) { EXPECT_STREQ(string_literal, "The answer is: %s"); } -TEST_F(TokenizeToCallback, Domain_Default) { - const char* tokenizer_domain = nullptr; - const char* string_literal = nullptr; - - PW_TOKENIZE_TO_CALLBACK(SetMessage, "The answer is: %s", "5432!"); - - EXPECT_STREQ(tokenizer_domain, PW_TOKENIZER_DEFAULT_DOMAIN); - EXPECT_STREQ(string_literal, "The answer is: %s"); -} - -TEST_F(TokenizeToCallback, Domain_Specified) { - const char* tokenizer_domain = nullptr; - const char* string_literal = nullptr; - - PW_TOKENIZE_TO_CALLBACK_DOMAIN( - "ThisIsTheDomain", SetMessage, "The answer is: %s", "5432!"); - - EXPECT_STREQ(tokenizer_domain, "ThisIsTheDomain"); - EXPECT_STREQ(string_literal, "The answer is: %s"); -} - } // namespace } // namespace pw::tokenizer diff --git a/pw_tokenizer/tokenize_test_c.c b/pw_tokenizer/tokenize_test_c.c index bf8877a68d..485bb50724 100644 --- a/pw_tokenizer/tokenize_test_c.c +++ b/pw_tokenizer/tokenize_test_c.c @@ -53,26 +53,6 @@ void pw_tokenizer_ToBufferTest_SequentialZigZag(void* buffer, (signed char)-7); } -void pw_tokenizer_ToCallbackTest_SequentialZigZag( - void (*callback)(const uint8_t* buffer, size_t size)) { - PW_TOKENIZE_TO_CALLBACK(callback, - TEST_FORMAT_SEQUENTIAL_ZIG_ZAG, - 0u, - -1, - 1u, - (unsigned)-2, - (unsigned short)2u, - (signed char)-3, - 3, - -4l, - 4ul, - -5ll, - 5ull, - (signed char)-6, - (char)6, - (signed char)-7); -} - void pw_tokenizer_ToBufferTest_Requires8(void* buffer, size_t* buffer_size) { PW_TOKENIZE_TO_BUFFER(buffer, buffer_size, TEST_FORMAT_REQUIRES_8, "hi", -7); } diff --git a/pw_tokenizer/tokenize_to_global_handler.cc b/pw_tokenizer/tokenize_to_global_handler.cc deleted file mode 100644 index 5ac2755298..0000000000 --- a/pw_tokenizer/tokenize_to_global_handler.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2020 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_tokenizer/tokenize_to_global_handler.h" - -#include "pw_tokenizer/encode_args.h" - -namespace pw { -namespace tokenizer { - -extern "C" void _pw_tokenizer_ToGlobalHandler(pw_tokenizer_Token token, - pw_tokenizer_ArgTypes types, - ...) { - va_list args; - va_start(args, types); - EncodedMessage encoded(token, types, args); - va_end(args); - - pw_tokenizer_HandleEncodedMessage(encoded.data_as_uint8(), encoded.size()); -} - -} // namespace tokenizer -} // namespace pw