Skip to content

Commit 5651fbe

Browse files
committed
Add logging to stage 2
1 parent d2c9ea8 commit 5651fbe

File tree

8 files changed

+150
-16
lines changed

8 files changed

+150
-16
lines changed

src/arm64/stage2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace simdjson {
1010
namespace arm64 {
1111

12+
#include "generic/stage2/logger.h"
1213
#include "generic/stage2/atomparsing.h"
1314
#include "generic/stage2/structural_iterator.h"
1415
#include "generic/stage2/structural_parser.h"

src/fallback/stage2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace simdjson {
88
namespace fallback {
99

10+
#include "generic/stage2/logger.h"
1011
#include "generic/stage2/atomparsing.h"
1112
#include "generic/stage2/structural_iterator.h"
1213
#include "generic/stage2/structural_parser.h"

src/generic/stage2/logger.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// This is for an internal-only stage 2 specific logger.
2+
// Set LOG_ENABLED = true to log what stage 2 is doing!
3+
namespace logger {
4+
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
5+
6+
static constexpr const bool LOG_ENABLED = false;
7+
static constexpr const int LOG_EVENT_LEN = 30;
8+
static constexpr const int LOG_BUFFER_LEN = 20;
9+
static constexpr const int LOG_DETAIL_LEN = 50;
10+
11+
static int log_depth; // Not threadsafe. Log only.
12+
13+
// Helper to turn unprintable or newline characters into spaces
14+
static really_inline char printable_char(char c) {
15+
if (c >= 0x20) {
16+
return c;
17+
} else {
18+
return ' ';
19+
}
20+
}
21+
22+
// Print the header and set up log_start
23+
static really_inline void log_start() {
24+
if (LOG_ENABLED) {
25+
log_depth = 0;
26+
printf("\n");
27+
printf("| %-*s | %-*s | %*s | %*s | %*s | %-*s |\n", LOG_EVENT_LEN, "Event", LOG_BUFFER_LEN, "Buffer", 4, "Curr", 4, "Next", 5, "Next#", LOG_DETAIL_LEN, "Detail");
28+
printf("|%.*s|%.*s|%.*s|%.*s|%.*s|%.*s|\n", LOG_EVENT_LEN+2, DASHES, LOG_BUFFER_LEN+2, DASHES, 4+2, DASHES, 4+2, DASHES, 5+2, DASHES, LOG_DETAIL_LEN+2, DASHES);
29+
}
30+
}
31+
32+
// Logs a single line of
33+
template<typename S>
34+
static really_inline void log_line(S &structurals, const char *title_prefix, const char *title, const char *detail) {
35+
if (LOG_ENABLED) {
36+
printf("| %*s%s%-*s ", log_depth*2, "", title_prefix, LOG_EVENT_LEN - log_depth*2 - int(strlen(title_prefix)), title);
37+
{
38+
// Print the next N characters in the buffer.
39+
printf("| ");
40+
if (structurals.at_beginning()) {
41+
// If the pointer is at the beginning, print a space followed by the beginning characters
42+
// Print spaces for unprintable or newline characters.
43+
printf(" ");
44+
for (int i=0;i<LOG_BUFFER_LEN-1;i++) {
45+
printf("%c", printable_char(structurals.buf[i]));
46+
}
47+
} else {
48+
// Otherwise, print the characters starting from the buffer position.
49+
// Print spaces for unprintable or newline characters.
50+
for (int i=0;i<LOG_BUFFER_LEN;i++) {
51+
printf("%c", printable_char(structurals.current()[i]));
52+
}
53+
}
54+
printf(" ");
55+
}
56+
printf("| %c ", printable_char(structurals.at_beginning() ? ' ' : structurals.current_char()));
57+
printf("| %c ", printable_char(structurals.peek_char()));
58+
printf("| %5zd ", structurals.next_structural);
59+
printf("| %-*s ", LOG_DETAIL_LEN, detail);
60+
printf("|\n");
61+
}
62+
}
63+
} // namespace logger
64+

src/generic/stage2/streaming_structural_parser.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ struct streaming_structural_parser: structural_parser {
55

66
// override to add streaming
77
WARN_UNUSED really_inline error_code start(UNUSED size_t len, ret_address finish_parser) {
8+
log_start();
89
init(); // sets is_valid to false
910
// Capacity ain't no thang for streaming, so we don't check it.
1011
// Advance to the first character as soon as possible
@@ -19,16 +20,20 @@ struct streaming_structural_parser: structural_parser {
1920
// override to add streaming
2021
WARN_UNUSED really_inline error_code finish() {
2122
if ( structurals.past_end(doc_parser.n_structural_indexes) ) {
23+
log_error("IMPOSSIBLE: past the end of the JSON!");
2224
return on_error(TAPE_ERROR);
2325
}
2426
end_document();
2527
if (depth != 0) {
28+
log_error("Unclosed objects or arrays!");
2629
return on_error(TAPE_ERROR);
2730
}
2831
if (doc_parser.containing_scope[depth].tape_index != 0) {
32+
log_error("IMPOSSIBLE: root scope tape index did not start at 0!");
2933
return on_error(TAPE_ERROR);
3034
}
3135
bool finished = structurals.at_end(doc_parser.n_structural_indexes);
36+
if (!finished) { log_value("(and has more)"); }
3237
return on_success(finished ? SUCCESS : SUCCESS_AND_HAS_MORE);
3338
}
3439
};
@@ -76,6 +81,7 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa
7681
);
7782
goto finish;
7883
default:
84+
parser.log_error("Document starts with a non-value character");
7985
goto error;
8086
}
8187

@@ -85,32 +91,34 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa
8591
object_begin:
8692
switch (parser.advance_char()) {
8793
case '"': {
88-
FAIL_IF( parser.parse_string() );
94+
FAIL_IF( parser.parse_string(true) );
8995
goto object_key_parser;
9096
}
9197
case '}':
9298
parser.end_object();
9399
goto scope_end;
94100
default:
101+
parser.log_error("Object does not start with a key");
95102
goto error;
96103
}
97104

98105
object_key_parser:
99-
FAIL_IF( parser.advance_char() != ':' );
106+
if (parser.advance_char() != ':' ) { parser.log_error("Missing colon after key in object"); goto error; }
100107
parser.increment_count();
101108
parser.advance_char();
102109
GOTO( parser.parse_value(addresses, addresses.object_continue) );
103110

104111
object_continue:
105112
switch (parser.advance_char()) {
106113
case ',':
107-
FAIL_IF( parser.advance_char() != '"' );
108-
FAIL_IF( parser.parse_string() );
114+
if (parser.advance_char() != '"' ) { parser.log_error("Key string missing at beginning of field in object"); goto error; }
115+
FAIL_IF( parser.parse_string(true) );
109116
goto object_key_parser;
110117
case '}':
111118
parser.end_object();
112119
goto scope_end;
113120
default:
121+
parser.log_error("No comma between object fields");
114122
goto error;
115123
}
116124

@@ -142,6 +150,7 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa
142150
parser.end_array();
143151
goto scope_end;
144152
default:
153+
parser.log_error("Missing comma between array values");
145154
goto error;
146155
}
147156

src/generic/stage2/structural_iterator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class structural_iterator {
1717
really_inline char current_char() {
1818
return c;
1919
}
20+
really_inline char peek_char() {
21+
return buf[structural_indexes[next_structural]];
22+
}
2023
really_inline const uint8_t* current() {
2124
return &buf[idx];
2225
}
@@ -54,6 +57,9 @@ class structural_iterator {
5457
really_inline bool at_end(uint32_t n_structural_indexes) {
5558
return next_structural+1 == n_structural_indexes;
5659
}
60+
really_inline bool at_beginning() {
61+
return next_structural == 0;
62+
}
5763
really_inline size_t next_structural_index() {
5864
return next_structural;
5965
}

0 commit comments

Comments
 (0)