Closed Garland815 closed 1 month ago
I've just tried this test.
//*************************************************************************
TEST(test_issue_971_etl_format_spec_width_method_not_working)
{
etl::format_spec formatSpec;
formatSpec.hex().width(2).fill('0').upper_case(true);
etl::string<80> strBuffer;
etl::string_stream strStream(strBuffer, formatSpec);
strStream << 1 << ", " << 0xAA;
std::string expected("01, AA");
std::string actual(strStream.str().c_str());
CHECK_EQUAL(expected, actual);
}
This passes and the output is "01, AA"
Are you including the string's terminating zero?
The strBuffer
contents should be
'1'
','
' '
'A'
'A'
'\0'
with a size()
of 6
.
Thanks for responding to this issue quickly.
Here is my exact code and details about the compiler and the target is XMC7200 MCU.
/*
C++ Standard: 201703
GCC Version: 11.3.1 20220712
Compiler command line:
ModusToolbox/tools_3.2/gcc/bin/arm-none-eabi-g++ -std=c++17 -c -mcpu=cortex-m7 --specs=nano.specs -Og -mfloat-abi=softfp -mfpu=fpv5-d16 -mthumb
-ffunction-sections -fdata-sections -ffat-lto-objects -g -Wall -pipe -fno-rtti -fno-exceptions -DCOMPONENT_APP_KIT_XMC72_EVK -DCOMPONENT_CAT1
-DCOMPONENT_CAT1C -DCOMPONENT_CAT1C8M -DCOMPONENT_CM7 -DCOMPONENT_CM7_0 -DCOMPONENT_Debug -DCOMPONENT_FREERTOS -DCOMPONENT_GCC_ARM
-DCOMPONENT_MW_ABSTRACTION_RTOS -DCOMPONENT_MW_CAT1CM0P -DCOMPONENT_MW_CLIB_SUPPORT -DCOMPONENT_MW_CMSIS -DCOMPONENT_MW_CORE_LIB
-DCOMPONENT_MW_CORE_MAKE -DCOMPONENT_MW_FREERTOS -DCOMPONENT_MW_MTB_HAL_CAT1 -DCOMPONENT_MW_MTB_PDL_CAT1 -DCOMPONENT_MW_RECIPE_MAKE_CAT1C
-DCOMPONENT_MW_RETARGET_IO -DCOMPONENT_SOFTFP -DCOMPONENT_XMC7xDUAL_CM0P_SLEEP -DCORE_NAME_CM7_0=1 -DCY_APPNAME_mtb_example_xmc7000_blinky_freertos
-DCY_SUPPORTS_DEVICE_VALIDATION -DCY_TARGET_BOARD=APP_KIT_XMC72_EVK -DCY_USING_HAL -DDEBUG -DTARGET_APP_KIT_XMC72_EVK -DXMC7200D_E272K8384
Calling code:
PrintDataHex(0x01, 0xAA); // Output: 010 AA0
*/
template<typename ... TArgs>
void PrintDataHex(TArgs &&...args)
{
etl::format_spec formatSpec;
formatSpec.hex().width(2).fill('0').upper_case(true); // .width(2) not work, print out 010, AA0 with extra 0 at the end.
etl::string < 80 > strBuffer; // String storage.
etl::string_stream strStream(strBuffer, formatSpec);
((strStream << args << " "), ...);
strBuffer.back() = 0; // Null terminated string. Null replaces last Space.
printf("%s\n", strBuffer.c_str()); // Print line
}
What is happening is that the format is extending the width of every input using the fill character.
0x01
-> 01
" "
-> "0 "
0xAA
-> AA
" "
-> "0 "
Results in "010 AA0 "
I need to check if the STL's std::ostringstream
does the same or not.
BTW: strBuffer.back() = 0
is not a good way of removing the last character, as it does not affect the value returned by size()
.
You should use pop_back()
.
My experiments with std::ostringstream
give these (odd) results.
std::ostringstream oss;
oss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase;
oss << " "; // "0 "
oss << " " << " "; // "0 "
oss << " " << " " << 0x01 << " "; // "0 1 "
oss << " " << 0x01 << " " << " "; // "0 1 "
oss << 0x01 << " " << " "; // "01 "
I'm not sure I can completely follow the logic behind the std::ostringstream
output.
At least the ETL's version is consistent.
This code works as expected.
template<typename ... TArgs>
void PrintDataHex(TArgs &&...args)
{
etl::format_spec formatHex;
formatHex.hex().width(2).fill('0').upper_case(true);
etl::format_spec formatNormal;
etl::string<80> strBuffer; // String storage.
etl::string_stream strStream(strBuffer);
((strStream << formatHex << args << formatNormal << " "), ...);
strBuffer.pop_back();
printf("%s\n", strBuffer.c_str()); // Print line
}
Thanks! This makes sense for the format spec applies to all << outputs afterwards.
Use
strStream <<
to format 1 and 0xAA will get010, AA0
with extra 0 at the end.