Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sjparser: Value<double> should also support yajl integers
Browse files Browse the repository at this point in the history
Previosly, sjparser was rejecting payloads like

   {
     "lat": 0,
     "lon": 0
   }

when using Value<double> ... However, since API users could
send both 0 and 0.0, we need to extent the allowed yajl types.
mmd-osm committed May 27, 2024
1 parent cd0c2d5 commit cde2407
Showing 4 changed files with 35 additions and 0 deletions.
4 changes: 4 additions & 0 deletions contrib/sjparser/library/sjparser/internals/token_parser.cpp
Original file line number Diff line number Diff line change
@@ -88,5 +88,9 @@ void TokenParser::on(ArrayEndT /*unused*/) {
unexpectedToken("array end");
} // LCOV_EXCL_LINE

void TokenParser::on(DummyT) {
unexpectedToken("dummy");
}

void TokenParser::childParsed() {}
} // namespace SJParser
22 changes: 22 additions & 0 deletions contrib/sjparser/library/sjparser/internals/token_parser.h
Original file line number Diff line number Diff line change
@@ -26,9 +26,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>

namespace SJParser {

struct DummyT {}; // not used by yajl
struct NullT {};
struct MapStartT {};
struct MapKeyT {
@@ -46,9 +48,28 @@ template <> struct TokenTypeResolver<std::string> {
using type = std::string_view;
};

template <> struct TokenTypeResolver<double> {
using type = double;
};

template <typename TokenT>
using TokenType = typename TokenTypeResolver<std::decay_t<TokenT>>::type;

// TokenSecondaryTypeResolver is used to indicate that a type (e.g. double)
// should also process yajl events for other data types (e.g. integers)
// Yajl treats numbers without decimal points as integer, and this
// triggers an error in case of Value<double>.
template <typename TokenT> struct TokenSecondaryTypeResolver {
using type = DummyT;
};

template <> struct TokenSecondaryTypeResolver<double> {
using type = int64_t;
};

template <typename TokenT>
using TokenSecondaryType = typename TokenSecondaryTypeResolver<std::decay_t<TokenT>>::type;

class Dispatcher;

class TokenParser {
@@ -70,6 +91,7 @@ class TokenParser {
virtual void on(MapEndT /*unused*/);
virtual void on(ArrayStartT /*unused*/);
virtual void on(ArrayEndT /*unused*/);
virtual void on(DummyT);

virtual void childParsed();

8 changes: 8 additions & 0 deletions contrib/sjparser/library/sjparser/value.cpp
Original file line number Diff line number Diff line change
@@ -63,6 +63,14 @@ template <typename ValueT> void Value<ValueT>::on(TokenType<ValueT> value) {
endParsing();
}

template <typename ValueT> void Value<ValueT>::on(TokenSecondaryType<ValueT> value) {
if constexpr (!std::is_same_v<TokenSecondaryType<ValueT>, SJParser::DummyT>) {
setNotEmpty();
_value = value;
endParsing();
}
}

template <typename ValueT> void Value<ValueT>::finish() {
if (_on_finish && !_on_finish(_value)) {
throw std::runtime_error("Callback returned false");
1 change: 1 addition & 0 deletions contrib/sjparser/library/sjparser/value.h
Original file line number Diff line number Diff line change
@@ -111,6 +111,7 @@ template <typename ValueT> class Value : public TokenParser {

private:
void on(TokenType<ValueType> value) override;
void on(TokenSecondaryType<ValueType> value) override;
void finish() override;

ValueType _value;

0 comments on commit cde2407

Please sign in to comment.