9 size_t len = strlen(line);
10 while (len > 0 && (line[len - 1] ==
'\r' || line[len - 1] ==
'\n')) {
32 snprintf(search,
sizeof(search),
"\"%s\":", key);
33 return strstr(json, search) != NULL;
38 snprintf(search,
sizeof(search),
"\"%s\":", key);
40 const char* pos = strstr(json, search);
43 pos += strlen(search);
44 while (*pos && isspace(*pos)) pos++;
47 double value = strtod(pos, &endptr);
49 if (pos == endptr)
return NAN;
56 snprintf(search,
sizeof(search),
"\"%s\":", key);
58 const char* pos = strstr(json, search);
61 pos += strlen(search);
62 while (*pos && isspace(*pos)) pos++;
65 long value = strtol(pos, &endptr, 10);
74 bool has_timestamp =
json_has_field(reader->line_buffer,
"timestamp");
81 int field_count = has_timestamp + has_open + has_high + has_low + has_close + has_volume;
83 if (field_count == 0) {
88 if (!has_timestamp || !has_open || !has_high || !has_low || !has_close || !has_volume) {
100 if (isnan(reader->data.candle.open) || isnan(reader->data.candle.high) ||
101 isnan(reader->data.candle.low) || isnan(reader->data.candle.close) ||
102 isnan(reader->data.candle.volume)) {
109 return &reader->data.candle;
117 bool has_timestamp =
json_has_field(reader->line_buffer,
"timestamp");
122 int field_count = has_timestamp + has_price + has_volume + has_side;
124 if (field_count == 0) {
129 if (!has_timestamp || !has_price || !has_volume || !has_side) {
139 reader->data.trade.side = (
WU_Side)side_value;
141 if (isnan(reader->data.trade.price) || isnan(reader->data.trade.volume)) {
148 return &reader->data.trade;
156 bool has_timestamp =
json_has_field(reader->line_buffer,
"timestamp");
159 int field_count = has_timestamp + has_value;
161 if (field_count == 0) {
166 if (!has_timestamp || !has_value) {
171 reader->data.single_value.timestamp.mark =
json_get_long_value(reader->line_buffer,
"timestamp");
174 if (isnan(reader->data.single_value.value)) {
181 return &reader->data.single_value;
191 if (!file)
return NULL;
192 WU_JsonReader reader = (WU_JsonReader)malloc(
sizeof(
struct WU_JsonReader_));
193 if (!reader)
return NULL;
196 reader->data_type = data_type;
201 reader->data.candle.timestamp.units = time_units;
205 reader->data.trade.timestamp.units = time_units;
209 reader->data.single_value.timestamp.units = time_units;
static void * read_candle_json(WU_JsonReader reader)
static double json_get_number_value(const char *json, const char *key)
static long json_get_long_value(const char *json, const char *key)
static void trim_line(char *line)
static void wu_json_reader_free(WU_JsonReader reader)
static bool read_line(WU_JsonReader reader)
WU_JsonReader wu_json_reader_new(FILE *file, WU_DataType data_type, WU_TimeUnit time_units)
static void * read_trade_json(WU_JsonReader reader)
static void * read_single_value_json(WU_JsonReader reader)
static bool json_has_field(const char *json, const char *key)
#define WU_JSON_MAX_LINE_SIZE
@ WU_JSON_ERROR_MISSING_FIELD
WU_JsonReader is a concrete implementation of the WU_Reader interface that reads data from a JSON Lin...
Base for a reader, which defines the minimal interface for reading the next data point from a data so...
WU_TimeUnit
WU_TimeUnit represents a unit of time used for time-based calculations such as time-weighted returns ...
WU_Side
WU_Side represents the direction of a signal or a trade.
WU_DataType
WU_DataType represents the type of input data, which can be a candle, a trade, or a single value.
@ WU_DATA_TYPE_SINGLE_VALUE