Skip to content

Commit

Permalink
Merge pull request #502 from nseam/dev-fixme
Browse files Browse the repository at this point in the history
Serializer: Bug fixes
  • Loading branch information
kenorb authored May 24, 2021
2 parents c601e09 + 26b6e6b commit f9e7b8c
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 15 deletions.
34 changes: 33 additions & 1 deletion Convert.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -312,22 +312,54 @@ public:
_out = _value != "" && _value != NULL && _value != "0" && _value != "false";
}

static void StringToType(string _value, char& _out) {
_out = (char)StringToInteger(_value);
}

static void StringToType(string _value, unsigned char& _out) {
_out = (unsigned char)StringToInteger(_value);
}

static void StringToType(string _value, int& _out) {
_out = (int)StringToInteger(_value);
}

static void StringToType(string _value, unsigned int& _out) {
_out = (unsigned int)StringToInteger(_value);
}

static void StringToType(string _value, long& _out) {
_out = StringToInteger(_value);
_out = (long)StringToInteger(_value);
}

static void StringToType(string _value, unsigned long& _out) {
_out = (unsigned long)StringToInteger(_value);
}

static void StringToType(string _value, short& _out) {
_out = (short) StringToInteger(_value);
}

static void StringToType(string _value, unsigned short& _out) {
_out = (unsigned short) StringToInteger(_value);
}

static void StringToType(string _value, float& _out) {
_out = (float)StringToDouble(_value);
}

static void StringToType(string _value, double& _out) {
_out = StringToDouble(_value);
}

static void StringToType(string _value, color& _out) {
_out = StringToColor(_value);
}

static void StringToType(string _value, datetime& _out) {
_out = StringToTime(_value);
}

static void StringToType(string _value, string& _out) {
_out = _value;
}
Expand Down
32 changes: 21 additions & 11 deletions Serializer.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define SERIALIZER_MQH

// Includes.
#include "Convert.mqh"
#include "DictBase.mqh"
#include "Log.mqh"
#include "Serializer.define.h"
Expand Down Expand Up @@ -60,6 +61,10 @@ class Serializer {
_logger = new Log();
_root_node_ownership = true;
fp_precision = SERIALIZER_DEFAULT_FP_PRECISION;
if (_flags == 0) {
// Preventing flags misuse.
_flags = SERIALIZER_FLAG_INCLUDE_ALL;
}
}

/**
Expand Down Expand Up @@ -208,6 +213,13 @@ class Serializer {
return true;
}

if ((field_flags & SERIALIZER_FIELD_FLAG_HIDDEN) == SERIALIZER_FIELD_FLAG_HIDDEN) {
if ((serializer_flags & SERIALIZER_FLAG_SKIP_HIDDEN) != SERIALIZER_FLAG_SKIP_HIDDEN) {
// Field is hidden, but serializer has no SERIALIZER_FLAG_SKIP_HIDDEN flag set, so field will be serialized.
return true;
}
}

// Is field hidden?
if ((serializer_flags & SERIALIZER_FLAG_SKIP_HIDDEN) == SERIALIZER_FLAG_SKIP_HIDDEN) {
if ((field_flags & SERIALIZER_FIELD_FLAG_HIDDEN) == SERIALIZER_FIELD_FLAG_HIDDEN) {
Expand All @@ -229,20 +241,20 @@ class Serializer {
}

// Is field dynamic?
if ((serializer_flags & SERIALIZER_FLAG_INCLUDE_DYNAMIC) != SERIALIZER_FLAG_INCLUDE_DYNAMIC) {
if ((serializer_flags & SERIALIZER_FLAG_INCLUDE_DYNAMIC) == SERIALIZER_FLAG_INCLUDE_DYNAMIC) {
if ((field_flags & SERIALIZER_FIELD_FLAG_DYNAMIC) == SERIALIZER_FIELD_FLAG_DYNAMIC) {
return false;
return true;
}
}

// Is field a feature?
if ((serializer_flags & SERIALIZER_FLAG_INCLUDE_FEATURE) != SERIALIZER_FLAG_INCLUDE_FEATURE) {
if ((serializer_flags & SERIALIZER_FLAG_INCLUDE_FEATURE) == SERIALIZER_FLAG_INCLUDE_FEATURE) {
if ((field_flags & SERIALIZER_FIELD_FLAG_FEATURE) == SERIALIZER_FIELD_FLAG_FEATURE) {
return false;
return true;
}
}

return true;
return false;
}

/**
Expand Down Expand Up @@ -306,11 +318,9 @@ class Serializer {
int num_items;

if (_mode == Serialize) {
if ((_flags & SERIALIZER_FLAG_SKIP_HIDDEN) == SERIALIZER_FLAG_SKIP_HIDDEN) {
if ((flags & SERIALIZER_FIELD_FLAG_HIDDEN) == SERIALIZER_FIELD_FLAG_HIDDEN) {
// Skipping prematurely instead of creating object by new.
return;
}
if (!IsFieldVisible(_flags, flags)) {
// Skipping prematurely instead of creating object by new.
return;
}
}

Expand Down Expand Up @@ -407,7 +417,7 @@ class Serializer {
value = (V)child.GetValueParam()._integral._double;
break;
case SerializerNodeParamString:
value = (V)(int)child.GetValueParam()._string;
Convert::StringToType(child.GetValueParam()._string, value);
break;
}

Expand Down
39 changes: 38 additions & 1 deletion SerializerJson.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ class SerializerJson {
k = i + 1;
do {
ch2 = StringGetCharacter(data, k++);
if (GetLastError() == 5041) {
ResetLastError();
ch2 = 0;
break;
}
} while (ch2 == ' ' || ch2 == '\t' || ch2 == '\n' || ch2 == '\r');

if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') continue;
Expand All @@ -169,14 +174,18 @@ class SerializerJson {
}
if (expectingKey) {
key = SerializerNodeParam::FromString(extracted);

expectingKey = false;
expectingSemicolon = true;
} else if (expectingValue) {
current.AddChild(new SerializerNode(
current.GetType() == SerializerNodeObject ? SerializerNodeObjectProperty : SerializerNodeArrayItem,
current, key, SerializerNodeParam::FromString(extracted)));

#ifdef __debug__
Print("SerializerJson: Value \"" + extracted + "\" for key " +
(key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

expectingValue = false;
} else {
return GracefulReturn("Unexpected '\"' symbol", i, root, key);
Expand All @@ -195,6 +204,10 @@ class SerializerJson {
return GracefulReturn("Cannot use object as a key", i, root, key);
}

#ifdef __debug__
Print("SerializerJson: Entering object for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

node = new SerializerNode(SerializerNodeObject, current, key);

if (!root) root = node;
Expand All @@ -212,9 +225,19 @@ class SerializerJson {
return GracefulReturn("Unexpected end of object", i, root, key);
}

#ifdef __debug__
Print("SerializerJson: Leaving object for key " + (current != NULL && current.GetKeyParam() != NULL
? ("\"" + current.GetKeyParam().ToString() + "\"")
: "<none>"));
#endif

current = current.GetParent();
expectingValue = false;
} else if (ch == '[') {
#ifdef __debug__
Print("SerializerJson: Entering list for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

if (expectingKey) {
return GracefulReturn("Cannot use array as a key", i, root, key);
}
Expand All @@ -230,6 +253,10 @@ class SerializerJson {
isOuterScope = false;
key = NULL;
} else if (ch == ']') {
#ifdef __debug__
Print("SerializerJson: Leaving list for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

if (expectingKey || expectingValue || current.GetType() != SerializerNodeArray) {
return GracefulReturn("Unexpected end of array", i, root, key);
}
Expand All @@ -247,6 +274,11 @@ class SerializerJson {

value = StringFind(extracted, ".") != -1 ? SerializerNodeParam::FromValue(StringToDouble(extracted))
: SerializerNodeParam::FromValue(StringToInteger(extracted));
#ifdef __debug__
Print("SerializerJson: Value " + value.AsString() + " for key " +
(key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

current.AddChild(new SerializerNode(
current.GetType() == SerializerNodeObject ? SerializerNodeObjectProperty : SerializerNodeArrayItem, current,
key, value));
Expand All @@ -262,6 +294,11 @@ class SerializerJson {

value = SerializerNodeParam::FromValue(ch == 't' ? true : false);

#ifdef __debug__
Print("SerializerJson: Value " + (value.ToBool() ? "true" : "false") + " for key " +
(key != NULL ? ("\"" + key.ToString() + "\"") : "<none>"));
#endif

// Skipping value.
i += ch == 't' ? 3 : 4;

Expand Down
9 changes: 8 additions & 1 deletion tests/ConfigTest.mq5
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ int OnInit() {
// @todo
// assertTrueOrFail(config.SaveToFile("config.ini", CONFIG_FORMAT_INI), "Cannot save config into the file!");
assertTrueOrFail(config.LoadFromFile<SerializerJson>("config.json"), "Cannot load config from the file!");

Print("There are ", config.Size(), " properites in config.");
Print("config[\"pair\"].type = \"", EnumToString(config["pair"].type), "\"");
Print("config[\"pair\"].string_value = \"", config["pair"].string_value, "\"");

assertTrueOrFail(config.LoadFromFile<SerializerJson>("config-minified.json"), "Cannot save config into the file!");

// @todo
Expand All @@ -109,10 +114,12 @@ int OnInit() {
configs.Push(config);

Print("There are ", configs[0].Size(), " properites in configs[0]!");
Print("configs[0][\"pair\"].type = \"", EnumToString(configs[0]["pair"].type), "\"");
Print("configs[0][\"pair\"].string_value = \"", configs[0]["pair"].string_value, "\"");

SerializerConverter stub = SerializerConverter::MakeStubObject<DictObject<int, Config>>(0, 1, configs[0].Size());

SerializerConverter::FromObject(configs, 0).ToFile<SerializerCsv>("config.csv", SERIALIZER_CSV_INCLUDE_TITLES, &stub);
SerializerConverter::FromObject(configs).ToFile<SerializerCsv>("config.csv", SERIALIZER_CSV_INCLUDE_TITLES, &stub);

SerializerConverter::FromObject(configs, 0).ToFile<SerializerJson>("config_2.json");

Expand Down
2 changes: 1 addition & 1 deletion tests/SerializerTest.mq5
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ int OnInit() {
buff_params.Add(limit, 5);
buff_params.Add(doubleVal, 6);

SerializerConverter stub5 = SerializerConverter::MakeStubObject<BufferStruct<DataParamEntry>>(0);
SerializerConverter stub5 = SerializerConverter::MakeStubObject<BufferStruct<DataParamEntry>>();
SerializerConverter::FromObject(buff_params)
.ToFile<SerializerCsv>("buffer_struct.csv", SERIALIZER_CSV_INCLUDE_TITLES_TREE | SERIALIZER_CSV_INCLUDE_KEY,
&stub5);
Expand Down

0 comments on commit f9e7b8c

Please sign in to comment.