Compare commits
No commits in common. "35ef94162bc1e31f93aa5f43636f4ec5cbe46010" and "3f698fb5f14273a9a613100a6ae97f3e1dc460ed" have entirely different histories.
35ef94162b
...
3f698fb5f1
119
.clang-format
119
.clang-format
@ -1,119 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
#
|
|
||||||
# clang-format configuration file. Intended for clang-format >= 11.
|
|
||||||
#
|
|
||||||
# For more information, see:
|
|
||||||
#
|
|
||||||
# Documentation/process/clang-format.rst
|
|
||||||
# https://clang.llvm.org/docs/ClangFormat.html
|
|
||||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
|
||||||
#
|
|
||||||
---
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AlignConsecutiveAssignments: false
|
|
||||||
AlignConsecutiveDeclarations: false
|
|
||||||
AlignEscapedNewlines: Left
|
|
||||||
AlignOperands: true
|
|
||||||
AlignTrailingComments: false
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
AllowShortBlocksOnASingleLine: false
|
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: None
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: false
|
|
||||||
BinPackArguments: true
|
|
||||||
BinPackParameters: true
|
|
||||||
BraceWrapping:
|
|
||||||
AfterClass: false
|
|
||||||
AfterControlStatement: false
|
|
||||||
AfterEnum: false
|
|
||||||
AfterFunction: true
|
|
||||||
AfterNamespace: true
|
|
||||||
AfterObjCDeclaration: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
IndentBraces: false
|
|
||||||
SplitEmptyFunction: true
|
|
||||||
SplitEmptyRecord: true
|
|
||||||
SplitEmptyNamespace: true
|
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BreakBeforeInheritanceComma: false
|
|
||||||
BreakBeforeTernaryOperators: false
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
BreakConstructorInitializers: BeforeComma
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakStringLiterals: false
|
|
||||||
ColumnLimit: 120
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ConstructorInitializerIndentWidth: 8
|
|
||||||
ContinuationIndentWidth: 8
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
DisableFormat: false
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
FixNamespaceComments: false
|
|
||||||
|
|
||||||
IncludeBlocks: Preserve
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 1
|
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
|
||||||
IndentCaseLabels: false
|
|
||||||
IndentGotoLabels: false
|
|
||||||
IndentPPDirectives: None
|
|
||||||
IndentWidth: 8
|
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
MacroBlockBegin: ''
|
|
||||||
MacroBlockEnd: ''
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: None
|
|
||||||
ObjCBinPackProtocolList: Auto
|
|
||||||
ObjCBlockIndentWidth: 8
|
|
||||||
ObjCSpaceAfterProperty: true
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
|
|
||||||
# Taken from git's rules
|
|
||||||
PenaltyBreakAssignment: 10
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 30
|
|
||||||
PenaltyBreakComment: 10
|
|
||||||
PenaltyBreakFirstLessLess: 0
|
|
||||||
PenaltyBreakString: 10
|
|
||||||
PenaltyExcessCharacter: 100
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
|
|
||||||
PointerAlignment: Right
|
|
||||||
ReflowComments: false
|
|
||||||
SortIncludes: false
|
|
||||||
SortUsingDeclarations: false
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterTemplateKeyword: true
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeInheritanceColon: true
|
|
||||||
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Standard: Cpp03
|
|
||||||
TabWidth: 8
|
|
||||||
UseTab: Always
|
|
||||||
...
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "test/catch2"]
|
|
||||||
path = test/catch2
|
|
||||||
url = https://git.shimatta.de/3rd-party/catch2.git
|
|
@ -5,5 +5,4 @@ aux_source_directory("src" SOURCES)
|
|||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
||||||
|
|
||||||
# Add tests. This is not included in the overall build
|
|
||||||
add_subdirectory(test)
|
|
||||||
|
@ -2,44 +2,16 @@
|
|||||||
#define _SIMPLE_PRINTF_H_
|
#define _SIMPLE_PRINTF_H_
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifndef SIMPLE_PRINTF_ATTR_FORMAT
|
#ifndef SIMPLE_PRINTF_ATTR_FORMAT
|
||||||
#if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
|
# if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
|
||||||
#define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
|
# define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
|
||||||
|
# else
|
||||||
|
# define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args)
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
#define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args)
|
# define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args)
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
#define SIMPLE_PRINTF_ATTR_FORMAT(fmt, args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum format_specifier_type {
|
|
||||||
FMT_INVALID = 0,
|
|
||||||
FMT_INTEGER,
|
|
||||||
FMT_UNSIGNED,
|
|
||||||
FMT_STRING,
|
|
||||||
FMT_HEXUINT_CAPITALIZED,
|
|
||||||
FMT_HEXUINT,
|
|
||||||
FMT_CHAR,
|
|
||||||
FMT_SIZE,
|
|
||||||
FMT_PERCENT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct format_specifier {
|
|
||||||
enum format_specifier_type specifier;
|
|
||||||
size_t length; /**< @brief lenght of formatted output.*/
|
|
||||||
bool zero_pad;
|
|
||||||
size_t length_of_provided_specifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper function to parse printf format specifiers
|
|
||||||
*
|
|
||||||
* @param start Start of parsing
|
|
||||||
* @param[out] result Result of format specifier parsing
|
|
||||||
*/
|
|
||||||
void parse_format_specifier(const char *start, struct format_specifier *result);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple implementation of snprintf
|
* @brief Simple implementation of snprintf
|
||||||
|
@ -2,6 +2,25 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
enum format_specifier_type {
|
||||||
|
FMT_INVALID = 0,
|
||||||
|
FMT_INTEGER,
|
||||||
|
FMT_UNSIGNED,
|
||||||
|
FMT_STRING,
|
||||||
|
FMT_HEXUINT_CAPITALIZED,
|
||||||
|
FMT_HEXUINT,
|
||||||
|
FMT_CHAR,
|
||||||
|
FMT_SIZE,
|
||||||
|
FMT_PERCENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct format_specifier {
|
||||||
|
enum format_specifier_type specifier;
|
||||||
|
size_t length; /**< @brief lenght of formatted output.*/
|
||||||
|
bool zero_pad;
|
||||||
|
size_t length_of_provided_specifier;
|
||||||
|
};
|
||||||
|
|
||||||
enum format_parser_state {
|
enum format_parser_state {
|
||||||
PARSER_PERCENT = 0,
|
PARSER_PERCENT = 0,
|
||||||
PARSER_SECOND,
|
PARSER_SECOND,
|
||||||
@ -68,7 +87,7 @@ static enum format_specifier_type resolve_specifier(char c)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_format_specifier(const char *start, struct format_specifier *result)
|
static void parse_format_specifier(const char *start, struct format_specifier *result)
|
||||||
{
|
{
|
||||||
size_t fmt_len = 1ull;
|
size_t fmt_len = 1ull;
|
||||||
bool keep_parsing = true;
|
bool keep_parsing = true;
|
||||||
@ -96,19 +115,15 @@ void parse_format_specifier(const char *start, struct format_specifier *result)
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case PARSER_PERCENT:
|
case PARSER_PERCENT:
|
||||||
if (*ptr == '%') {
|
if (*ptr == '%') {
|
||||||
advance_ptr = true;
|
advance_ptr++;
|
||||||
next_state = PARSER_SECOND;
|
next_state = PARSER_SECOND;
|
||||||
} else {
|
|
||||||
keep_parsing = false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PARSER_SECOND:
|
case PARSER_SECOND:
|
||||||
if (*ptr == '0') {
|
if (*ptr == '0') {
|
||||||
result->zero_pad = true;
|
result->zero_pad = true;
|
||||||
advance_ptr = true;
|
advance_ptr++;
|
||||||
next_state = PARSER_NUM;
|
next_state = PARSER_NUM;
|
||||||
current_token = ptr + 1;
|
|
||||||
token_length = 0;
|
|
||||||
} else if (*ptr > '9' || *ptr < '0') {
|
} else if (*ptr > '9' || *ptr < '0') {
|
||||||
/* Specifier */
|
/* Specifier */
|
||||||
next_state = PARSER_SPECIFIER;
|
next_state = PARSER_SPECIFIER;
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
project(simple-printf-test)
|
|
||||||
|
|
||||||
add_subdirectory(catch2 EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
add_custom_target(test "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" "-r compact" "-s" DEPENDS ${PROJECT_NAME})
|
|
||||||
|
|
||||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/catch-framework")
|
|
||||||
aux_source_directory("src" TEST_SOURCES)
|
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE simple-printf Catch2::Catch2WithMain)
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 0631b607ee2bbc07c7c238f0b15b23ef21926960
|
|
@ -1,114 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <simple-printf/simple-printf.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Invalid Specifier")
|
|
||||||
{
|
|
||||||
const char *tst = "%m";
|
|
||||||
const char *tst2 = "%45m";
|
|
||||||
const char *tst3 = "%014m";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
REQUIRE(result.specifier == FMT_INVALID);
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
REQUIRE(result.specifier == FMT_INVALID);
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
REQUIRE(result.specifier == FMT_INVALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Format Specifier c", "Char")
|
|
||||||
{
|
|
||||||
const char *tst = "%c";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 2);
|
|
||||||
REQUIRE(result.specifier == FMT_CHAR);
|
|
||||||
REQUIRE(result.zero_pad == false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Format Specifier s", "String")
|
|
||||||
{
|
|
||||||
const char *tst = "%s";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 2);
|
|
||||||
REQUIRE(result.specifier == FMT_STRING);
|
|
||||||
REQUIRE(result.length == 0);
|
|
||||||
REQUIRE(result.zero_pad == false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Format Specifier 04s", "String")
|
|
||||||
{
|
|
||||||
const char *tst = "%04s";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
|
|
||||||
REQUIRE(result.specifier == FMT_STRING);
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 4);
|
|
||||||
REQUIRE(result.length == 4);
|
|
||||||
REQUIRE(result.zero_pad == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Format Specifier 08x", "hex")
|
|
||||||
{
|
|
||||||
const char *tst = "%08x";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
|
|
||||||
REQUIRE(result.specifier == FMT_HEXUINT);
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 4);
|
|
||||||
REQUIRE(result.length == 8);
|
|
||||||
REQUIRE(result.zero_pad == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Format Specifier 08x with stuff", "hex")
|
|
||||||
{
|
|
||||||
const std::array<std::string, 8> tst_arr {
|
|
||||||
std::move(std::string("%08xff458578")),
|
|
||||||
std::move(std::string("%08x45578")),
|
|
||||||
std::move(std::string("%08xx458578")),
|
|
||||||
std::move(std::string("%08x44458578")),
|
|
||||||
std::move(std::string("%08x45sdf458578")),
|
|
||||||
std::move(std::string("%08xsfsdf4558578")),
|
|
||||||
std::move(std::string("%08xX")),
|
|
||||||
std::move(std::string("%08xdsda"))
|
|
||||||
};
|
|
||||||
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
for (const auto &tst : tst_arr) {
|
|
||||||
parse_format_specifier(tst.c_str(), &result);
|
|
||||||
REQUIRE(result.specifier == FMT_HEXUINT);
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 4);
|
|
||||||
REQUIRE(result.length == 8);
|
|
||||||
REQUIRE(result.zero_pad == true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Parse Percent spefifier")
|
|
||||||
{
|
|
||||||
const char *tst = "%%";
|
|
||||||
struct format_specifier result;
|
|
||||||
|
|
||||||
parse_format_specifier(tst, &result);
|
|
||||||
|
|
||||||
REQUIRE(result.specifier == FMT_PERCENT);
|
|
||||||
REQUIRE(result.length_of_provided_specifier == 2);
|
|
||||||
REQUIRE(result.length == 0);
|
|
||||||
REQUIRE(result.zero_pad == false);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user