Skip to content

Commit 2360bde

Browse files
Add clang-format for code style enforcement
- Add .clang-format configuration matching existing code style - Add CI workflow to check formatting on push/PR - Add make format and make format-check targets - Update DEVELOPMENT.md with clang-format requirements - Add missing stdint.h include in binary.h - Format all C++ source files
1 parent fbe4a27 commit 2360bde

31 files changed

+4214
-4048
lines changed

.clang-format

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# clang-format configuration for memtier_benchmark
2+
# Based on analysis of existing code style
3+
4+
BasedOnStyle: LLVM
5+
6+
# Indentation
7+
IndentWidth: 4
8+
TabWidth: 4
9+
UseTab: Never
10+
ContinuationIndentWidth: 4
11+
AccessModifierOffset: -4
12+
13+
# Brace style: opening brace on new line for functions, same line for control structures
14+
BreakBeforeBraces: Custom
15+
BraceWrapping:
16+
AfterClass: true
17+
AfterControlStatement: Never
18+
AfterEnum: true
19+
AfterFunction: true
20+
AfterNamespace: true
21+
AfterStruct: true
22+
AfterUnion: true
23+
BeforeCatch: false
24+
BeforeElse: false
25+
IndentBraces: false
26+
27+
# Constructor initializer lists - colon on same line, break after colon
28+
BreakConstructorInitializers: AfterColon
29+
ConstructorInitializerIndentWidth: 8
30+
PackConstructorInitializers: NextLine
31+
32+
# Line width
33+
ColumnLimit: 120
34+
35+
# Pointer/reference alignment - space before * (Right alignment)
36+
PointerAlignment: Right
37+
ReferenceAlignment: Right
38+
39+
# Spaces
40+
SpaceAfterCStyleCast: true
41+
SpaceBeforeAssignmentOperators: true
42+
SpaceBeforeParens: ControlStatements
43+
SpacesInAngles: Never
44+
SpacesInParentheses: false
45+
46+
# IMPORTANT: Do not sort includes - breaks build due to header dependencies
47+
IncludeBlocks: Preserve
48+
SortIncludes: Never
49+
50+
# Short statements
51+
AllowShortBlocksOnASingleLine: Empty
52+
AllowShortFunctionsOnASingleLine: Inline
53+
AllowShortIfStatementsOnASingleLine: WithoutElse
54+
AllowShortLoopsOnASingleLine: false
55+
56+
# Other
57+
AlignTrailingComments: true
58+
AlwaysBreakAfterReturnType: None
59+
KeepEmptyLinesAtTheStartOfBlocks: false
60+
MaxEmptyLinesToKeep: 2
61+
SpaceBeforeCpp11BracedList: false
62+
Cpp11BracedListStyle: true
63+

.github/workflows/code-style.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Code Style
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
cpp-format-check:
7+
name: C++ Format Check
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v4
11+
12+
- name: Install clang-format
13+
run: |
14+
sudo apt-get update
15+
sudo apt-get install -y clang-format
16+
17+
- name: Check C++ formatting
18+
run: |
19+
# Find all C++ source files
20+
CPP_FILES=$(find . -name "*.cpp" -o -name "*.h" | grep -v deps/ | grep -v autom4te.cache/ | sort)
21+
22+
# Check formatting (dry-run)
23+
FAILED=0
24+
for file in $CPP_FILES; do
25+
if ! clang-format --dry-run --Werror "$file" 2>/dev/null; then
26+
echo "::error file=$file::File needs formatting: $file"
27+
FAILED=1
28+
fi
29+
done
30+
31+
if [ $FAILED -eq 1 ]; then
32+
echo ""
33+
echo "Some files need formatting. Run locally:"
34+
echo " make format"
35+
exit 1
36+
fi
37+
38+
echo "All C++ files are properly formatted!"
39+

DEVELOPMENT.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ The following tools are required:
1717
* pkg-config
1818
* GNU make
1919
* GCC C++ compiler
20+
* clang-format (for code formatting)
2021

2122
### CentOS/Red Hat Linux 7 or newer
2223

2324
Use the following to install prerequisites:
2425
```
2526
$ sudo yum install autoconf automake make gcc-c++ \
26-
zlib-devel libmemcached-devel libevent-devel openssl-devel
27+
zlib-devel libmemcached-devel libevent-devel openssl-devel \
28+
clang-tools-extra
2729
```
2830

2931
### Ubuntu/Debian
@@ -32,15 +34,15 @@ Use the following to install prerequisites:
3234

3335
```
3436
$ sudo apt-get install build-essential autoconf automake \
35-
libevent-dev pkg-config zlib1g-dev libssl-dev
37+
libevent-dev pkg-config zlib1g-dev libssl-dev clang-format
3638
```
3739

3840
### macOS
3941

4042
To build natively on macOS, use Homebrew to install the required dependencies:
4143

4244
```
43-
$ brew install autoconf automake libtool libevent pkg-config [email protected]
45+
$ brew install autoconf automake libtool libevent pkg-config [email protected] clang-format
4446
```
4547

4648
When running `./configure`, if it fails to find libssl it may be necessary to
@@ -74,6 +76,22 @@ $ ./configure CXXFLAGS="-g -O0 -Wall"
7476

7577
This disables optimizations (`-O0`), making it easier to step through code in a debugger, but should not be used for performance testing or production.
7678

79+
### Code Style
80+
81+
This project uses `clang-format` for consistent C++ code formatting. The style configuration is defined in `.clang-format`.
82+
83+
To format all C++ files:
84+
```
85+
$ make format
86+
```
87+
88+
To check formatting without modifying files:
89+
```
90+
$ make format-check
91+
```
92+
93+
CI will automatically check that all C++ files are properly formatted on every push and pull request.
94+
7795
## Testing
7896

7997
The project includes a basic set of integration tests.

JSON_handler.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include <stdlib.h>
2424
#include <string.h>
25-
#include <cmath> // For std::isnan
25+
#include <cmath> // For std::isnan
2626
#include "JSON_handler.h"
2727

2828

@@ -32,7 +32,7 @@
3232
* Opens the file named jsonfilename and sets the first nesting as NESTED_GENERAL
3333
* In case of failure to create the file, will state the error perror
3434
*/
35-
json_handler::json_handler(const char * jsonfilename) : m_json_file(NULL)
35+
json_handler::json_handler(const char *jsonfilename) : m_json_file(NULL)
3636
{
3737
// Try to open a file and add the first level
3838
m_json_file = fopen(jsonfilename, "w");
@@ -41,7 +41,7 @@ json_handler::json_handler(const char * jsonfilename) : m_json_file(NULL)
4141
}
4242
// opening the JSON
4343
fprintf(stderr, "Json file %s created...\n", jsonfilename);
44-
fprintf(m_json_file,"{");
44+
fprintf(m_json_file, "{");
4545
m_nest_closer_types.push_back(NESTED_GENERAL);
4646
beutify();
4747
}
@@ -53,9 +53,10 @@ json_handler::json_handler(const char * jsonfilename) : m_json_file(NULL)
5353
*/
5454
json_handler::~json_handler()
5555
{
56-
if (m_json_file){
56+
if (m_json_file) {
5757
// close nesting...
58-
while (close_nesting());
58+
while (close_nesting())
59+
;
5960
fclose(m_json_file);
6061
fprintf(stderr, "Json file closed.\n");
6162
}
@@ -66,7 +67,7 @@ json_handler::~json_handler()
6667
* based on the format defined
6768
* basically uses fprintf with the same parameters.
6869
*/
69-
void json_handler::write_obj(const char * objectname, const char * format, ...)
70+
void json_handler::write_obj(const char *objectname, const char *format, ...)
7071
{
7172
fprintf(m_json_file, "\"%s\": ", objectname);
7273
va_list argptr;
@@ -76,7 +77,7 @@ void json_handler::write_obj(const char * objectname, const char * format, ...)
7677
// Use a temporary va_list to check the string argument without advancing the original
7778
va_list tmp_argptr;
7879
va_copy(tmp_argptr, argptr);
79-
const char *str_arg = va_arg(tmp_argptr, const char*);
80+
const char *str_arg = va_arg(tmp_argptr, const char *);
8081
va_end(tmp_argptr);
8182

8283
if (str_arg == nullptr) {
@@ -99,8 +100,7 @@ void json_handler::write_obj(const char * objectname, const char * format, ...)
99100
} else {
100101
vfprintf(m_json_file, format, argptr);
101102
}
102-
}
103-
else {
103+
} else {
104104
// For other format specifiers, proceed as usual
105105
vfprintf(m_json_file, format, argptr);
106106
}
@@ -114,10 +114,10 @@ void json_handler::write_obj(const char * objectname, const char * format, ...)
114114
* in case objectname == NULL it will not add the title and just start nesting
115115
* The type defines the kind of charecters that will be used
116116
*/
117-
void json_handler::open_nesting(const char * objectname,eJSON_NESTED_TYPE type /*= NESTED_GENERAL*/)
117+
void json_handler::open_nesting(const char *objectname, eJSON_NESTED_TYPE type /*= NESTED_GENERAL*/)
118118
{
119-
const char * nestStart = (type == NESTED_GENERAL) ? "{" : "[";
120-
if (objectname != NULL){
119+
const char *nestStart = (type == NESTED_GENERAL) ? "{" : "[";
120+
if (objectname != NULL) {
121121
fprintf(m_json_file, "\"%s\":", objectname);
122122
}
123123
fprintf(m_json_file, "%s", nestStart);
@@ -134,17 +134,15 @@ void json_handler::open_nesting(const char * objectname,eJSON_NESTED_TYPE type /
134134
int json_handler::close_nesting()
135135
{
136136
int nest_level = m_nest_closer_types.size();
137-
if (nest_level > 0)
138-
{
137+
if (nest_level > 0) {
139138
eJSON_NESTED_TYPE type = m_nest_closer_types.back();
140139
m_nest_closer_types.pop_back();
141140
// as we assume that the last value is always a ',' or '\n' we need to remove it first
142141
fseek(m_json_file, -1, SEEK_CUR);
143-
const char * nestEnd = (type == NESTED_GENERAL) ? "}" : "]";
142+
const char *nestEnd = (type == NESTED_GENERAL) ? "}" : "]";
144143
fprintf(m_json_file, "%s", nestEnd);
145144
beutify();
146-
if (nest_level > 1)
147-
{
145+
if (nest_level > 1) {
148146
fprintf(m_json_file, ",");
149147
}
150148
}
@@ -156,14 +154,11 @@ int json_handler::close_nesting()
156154
*/
157155
void json_handler::beutify(bool only_tabs)
158156
{
159-
if (only_tabs == false)
160-
{
157+
if (only_tabs == false) {
161158
fprintf(m_json_file, "\n");
162159
}
163160
int nest_level = m_nest_closer_types.size();
164-
for(;nest_level>0;nest_level--)
165-
{
161+
for (; nest_level > 0; nest_level--) {
166162
fprintf(m_json_file, "\t");
167163
}
168-
169164
}

JSON_handler.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,31 @@
2525
#include <list>
2626

2727
// enum for holding type of nesting
28-
typedef enum{
28+
typedef enum
29+
{
2930
NESTED_GENERAL, // {}
3031
NESTED_ARRAY // []
31-
}eJSON_NESTED_TYPE;
32+
} eJSON_NESTED_TYPE;
3233

3334
/** represents an JSON handler, At this phase, only writes to JSON. */
34-
class json_handler {
35+
class json_handler
36+
{
3537
protected:
36-
FILE * m_json_file;
38+
FILE *m_json_file;
3739
// This list is used later for closing the nesting
38-
std::list<eJSON_NESTED_TYPE> m_nest_closer_types;
40+
std::list<eJSON_NESTED_TYPE> m_nest_closer_types;
3941
void beutify(bool only_tabs = false);
42+
4043
public:
41-
json_handler(const char * jsonfilename);
44+
json_handler(const char *jsonfilename);
4245
~json_handler();
4346

4447
// Write a single object to JSON
45-
void write_obj(const char * objectname, const char * format, ...);
48+
void write_obj(const char *objectname, const char *format, ...);
4649

4750
// Starts nesting, the type is used for deciding which charecter to be used for opening and closing
4851
// the nesting ('{}','[]')
49-
void open_nesting(const char * objectname,eJSON_NESTED_TYPE type = NESTED_GENERAL);
52+
void open_nesting(const char *objectname, eJSON_NESTED_TYPE type = NESTED_GENERAL);
5053

5154
// returns the nested level left after closing
5255
int close_nesting();

Makefile.am

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,26 @@ dist_man1_MANS = memtier_benchmark.1
7070
.PHONY: rebuild-man
7171
rebuild-man:
7272
help2man --name="NoSQL benchmark tool" --no-info --no-discard-stderr --output=memtier_benchmark.1 $(builddir)/memtier_benchmark
73+
74+
# Code formatting
75+
.PHONY: format format-check
76+
format:
77+
@echo "Formatting C++ source files..."
78+
@find $(srcdir) -name "*.cpp" -o -name "*.h" | grep -v deps/ | grep -v autom4te.cache/ | xargs clang-format -i
79+
@echo "Done."
80+
81+
format-check:
82+
@echo "Checking C++ source file formatting..."
83+
@FAILED=0; \
84+
for file in $$(find $(srcdir) -name "*.cpp" -o -name "*.h" | grep -v deps/ | grep -v autom4te.cache/); do \
85+
if ! clang-format --dry-run --Werror "$$file" 2>/dev/null; then \
86+
echo "Needs formatting: $$file"; \
87+
FAILED=1; \
88+
fi; \
89+
done; \
90+
if [ $$FAILED -eq 1 ]; then \
91+
echo ""; \
92+
echo "Some files need formatting. Run: make format"; \
93+
exit 1; \
94+
fi; \
95+
echo "All C++ files are properly formatted!"

0 commit comments

Comments
 (0)