Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2017-06-21 01:07:36 +0300
committerYuri Gorshenin <mipt.vi002@gmail.com>2017-07-05 16:41:38 +0300
commit41800988f08780d79efe5db10ddd8e15a060929f (patch)
treeff2687c229b9eeb6de695e272383788be96302d7
parent56347174828c1982b397a4671b1e9991d209a912 (diff)
[ugc] Template and macro magic for visitors.
-rw-r--r--ugc/serdes.hpp170
-rw-r--r--ugc/types.hpp70
-rw-r--r--ugc/ugc_tests/serdes_tests.cpp17
3 files changed, 111 insertions, 146 deletions
diff --git a/ugc/serdes.hpp b/ugc/serdes.hpp
index f799403dcf..a6be07e468 100644
--- a/ugc/serdes.hpp
+++ b/ugc/serdes.hpp
@@ -28,63 +28,33 @@ class Serializer
public:
Serializer(Sink & sink, HeaderV0 const & header) : m_sink(sink), m_header(header) {}
- void operator()(uint8_t const d) { WriteToSink(m_sink, d); }
- void operator()(uint32_t const d) { WriteToSink(m_sink, d); }
- void operator()(uint64_t const d) { WriteToSink(m_sink, d); }
- void operator()(std::string const & s) { utils::WriteString(m_sink, s); }
+ void operator()(uint8_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
+ void operator()(uint32_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
+ void operator()(uint64_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
+ void operator()(std::string const & s, char const * /* name */ = nullptr)
+ {
+ utils::WriteString(m_sink, s);
+ }
- void SerRating(float const f)
+ void VisitRating(float const f, char const * /* name */ = nullptr)
{
CHECK_GREATER_OR_EQUAL(f, 0.0, ());
auto const d = static_cast<uint32_t>(round(f * 10));
- SerVarUint(d);
+ VisitVarUint(d);
}
template <typename T>
- void SerVarUint(T const & t)
+ void VisitVarUint(T const & t, char const * /* name */ = nullptr)
{
WriteVarUint(m_sink, t);
}
- template <typename T>
- void operator()(vector<T> const & vs)
- {
- SerVarUint(static_cast<uint32_t>(vs.size()));
- for (auto const & v : vs)
- (*this)(v);
- }
-
- void operator()(RatingRecord const & ratingRecord)
+ void operator()(Time const & t, char const * /* name */ = nullptr)
{
- (*this)(ratingRecord.m_key);
- SerRating(ratingRecord.m_value);
+ VisitVarUint(ToDaysSinceEpoch(t));
}
- void operator()(Rating const & rating)
- {
- (*this)(rating.m_ratings);
- SerRating(rating.m_aggValue);
- }
-
- void operator()(UID const & uid)
- {
- (*this)(uid.m_hi);
- (*this)(uid.m_lo);
- }
-
- void operator()(Author const & author)
- {
- (*this)(author.m_uid);
- (*this)(author.m_name);
- }
-
- void operator()(Text const & text)
- {
- (*this)(text.m_lang);
- (*this)(text.m_text);
- }
-
- void operator()(Sentiment sentiment)
+ void operator()(Sentiment sentiment, char const * /* name */ = nullptr)
{
switch (sentiment)
{
@@ -93,27 +63,18 @@ public:
}
}
- void operator()(Review const & review)
- {
- (*this)(review.m_id);
- (*this)(review.m_text);
- (*this)(review.m_author);
- SerRating(review.m_rating);
- (*this)(review.m_sentiment);
- SerVarUint(review.DaysSinceEpoch());
- }
-
- void operator()(Attribute const & attribute)
+ template <typename T>
+ void operator()(vector<T> const & vs, char const * /* name */ = nullptr)
{
- (*this)(attribute.m_key);
- (*this)(attribute.m_value);
+ VisitVarUint(static_cast<uint32_t>(vs.size()));
+ for (auto const & v : vs)
+ (*this)(v);
}
- void operator()(UGC const & ugc)
+ template <typename R>
+ void operator()(R const & r, char const * /* name */ = nullptr)
{
- (*this)(ugc.m_rating);
- (*this)(ugc.m_reviews);
- (*this)(ugc.m_attributes);
+ r.Visit(*this);
}
private:
@@ -127,70 +88,47 @@ class DeserializerV0
public:
DeserializerV0(Source & source, HeaderV0 const & header) : m_source(source), m_header(header) {}
- void operator()(uint8_t & d) { ReadPrimitiveFromSource(m_source, d); }
- void operator()(uint32_t & d) { ReadPrimitiveFromSource(m_source, d); }
- void operator()(uint64_t & d) { ReadPrimitiveFromSource(m_source, d); }
- void operator()(std::string & s) { utils::ReadString(m_source, s); }
-
- void DesRating(float & f)
- {
- uint32_t d = 0;
- DesVarUint(d);
- f = static_cast<float>(d) / 10;
- }
-
- template <typename T>
- void DesVarUint(T & t)
+ void operator()(uint8_t & d, char const * /* name */ = nullptr)
{
- t = ReadVarUint<T, Source>(m_source);
+ ReadPrimitiveFromSource(m_source, d);
}
-
- template <typename T>
- T DesVarUint()
+ void operator()(uint32_t & d, char const * /* name */ = nullptr)
{
- return ReadVarUint<T, Source>(m_source);
+ ReadPrimitiveFromSource(m_source, d);
}
-
- void operator()(RatingRecord & ratingRecord)
+ void operator()(uint64_t & d, char const * /* name */ = nullptr)
{
- (*this)(ratingRecord.m_key);
- DesRating(ratingRecord.m_value);
+ ReadPrimitiveFromSource(m_source, d);
}
-
- template <typename T>
- void operator()(vector<T> & vs)
+ void operator()(std::string & s, char const * /* name */ = nullptr)
{
- auto const size = DesVarUint<uint32_t>();
- vs.resize(size);
- for (auto & v : vs)
- (*this)(v);
+ utils::ReadString(m_source, s);
}
- void operator()(Rating & rating)
+ void VisitRating(float & f, char const * /* name */ = nullptr)
{
- (*this)(rating.m_ratings);
- DesRating(rating.m_aggValue);
+ auto const d = DesVarUint<uint32_t>();
+ f = static_cast<float>(d) / 10;
}
- void operator()(UID & uid)
+ template <typename T>
+ void VisitVarUint(T & t, char const * /* name */ = nullptr)
{
- (*this)(uid.m_hi);
- (*this)(uid.m_lo);
+ t = ReadVarUint<T, Source>(m_source);
}
- void operator()(Author & author)
+ template <typename T>
+ T DesVarUint()
{
- (*this)(author.m_uid);
- (*this)(author.m_name);
+ return ReadVarUint<T, Source>(m_source);
}
- void operator()(Text & text)
+ void operator()(Time & t, char const * /* name */ = nullptr)
{
- (*this)(text.m_lang);
- (*this)(text.m_text);
+ t = FromDaysSinceEpoch(DesVarUint<uint32_t>());
}
- void operator()(Sentiment & sentiment)
+ void operator()(Sentiment & sentiment, char const * /* name */ = nullptr)
{
uint8_t s = 0;
(*this)(s);
@@ -202,27 +140,19 @@ public:
}
}
- void operator()(Review & review)
- {
- (*this)(review.m_id);
- (*this)(review.m_text);
- (*this)(review.m_author);
- DesRating(review.m_rating);
- (*this)(review.m_sentiment);
- review.SetDaysSinceEpoch(DesVarUint<uint32_t>());
- }
-
- void operator()(Attribute & attribute)
+ template <typename T>
+ void operator()(vector<T> & vs, char const * /* name */ = nullptr)
{
- (*this)(attribute.m_key);
- (*this)(attribute.m_value);
+ auto const size = DesVarUint<uint32_t>();
+ vs.resize(size);
+ for (auto & v : vs)
+ (*this)(v);
}
- void operator()(UGC & ugc)
+ template <typename R>
+ void operator()(R & r, char const * /* name */ = nullptr)
{
- (*this)(ugc.m_rating);
- (*this)(ugc.m_reviews);
- (*this)(ugc.m_attributes);
+ r.Visit(*this);
}
private:
diff --git a/ugc/types.hpp b/ugc/types.hpp
index 1fffe74d07..32e4e2cd64 100644
--- a/ugc/types.hpp
+++ b/ugc/types.hpp
@@ -4,7 +4,6 @@
#include "coding/hex.hpp"
-
#include <chrono>
#include <cstdint>
#include <memory>
@@ -13,6 +12,18 @@
#include <string>
#include <vector>
+#define DECLARE_VISITOR(...) \
+ template <typename Visitor> \
+ void Visit(Visitor & visitor) \
+ { \
+ __VA_ARGS__; \
+ } \
+ template <typename Visitor> \
+ void Visit(Visitor & visitor) const \
+ { \
+ __VA_ARGS__; \
+ }
+
namespace ugc
{
using TranslationKey = std::string;
@@ -33,11 +44,25 @@ inline std::string DebugPrint(Sentiment const & sentiment)
}
}
+inline uint32_t ToDaysSinceEpoch(Time const & time)
+{
+ auto const hours = std::chrono::duration_cast<std::chrono::hours>(time.time_since_epoch());
+ return static_cast<uint32_t>(hours.count()) / 24;
+}
+
+inline Time FromDaysSinceEpoch(uint32_t days)
+{
+ auto const hours = std::chrono::hours(days * 24);
+ return Time(hours);
+}
+
struct RatingRecord
{
RatingRecord() = default;
RatingRecord(TranslationKey const & key, float const value) : m_key(key), m_value(value) {}
+ DECLARE_VISITOR(visitor(m_key, "key"), visitor.VisitRating(m_value, "value"))
+
bool operator==(RatingRecord const & rhs) const
{
return m_key == rhs.m_key && m_value == rhs.m_value;
@@ -62,6 +87,8 @@ struct Rating
{
}
+ DECLARE_VISITOR(visitor(m_ratings, "ratings"), visitor.VisitRating(m_aggValue, "aggValue"))
+
bool operator==(Rating const & rhs) const
{
return m_ratings == rhs.m_ratings && m_aggValue == rhs.m_aggValue;
@@ -70,8 +97,8 @@ struct Rating
friend std::string DebugPrint(Rating const & rating)
{
std::ostringstream os;
- os << "Rating [ ratings:" << ::DebugPrint(rating.m_ratings) << ", aggValue:" << rating.m_aggValue
- << " ]";
+ os << "Rating [ ratings:" << ::DebugPrint(rating.m_ratings)
+ << ", aggValue:" << rating.m_aggValue << " ]";
return os.str();
}
@@ -86,8 +113,9 @@ struct UID
std::string ToString() const { return NumToHex(m_hi) + NumToHex(m_lo); }
- bool operator==(UID const & rhs) const { return m_hi == rhs.m_hi && m_lo == rhs.m_lo; }
+ DECLARE_VISITOR(visitor(m_hi, "hi"), visitor(m_lo, "lo"));
+ bool operator==(UID const & rhs) const { return m_hi == rhs.m_hi && m_lo == rhs.m_lo; }
friend std::string DebugPrint(UID const & uid)
{
std::ostringstream os;
@@ -104,8 +132,9 @@ struct Author
Author() = default;
Author(UID const & uid, std::string const & name) : m_uid(uid), m_name(name) {}
- bool operator==(Author const & rhs) const { return m_uid == rhs.m_uid && m_name == rhs.m_name; }
+ DECLARE_VISITOR(visitor(m_uid, "uid"), visitor(m_name, "name"));
+ bool operator==(Author const & rhs) const { return m_uid == rhs.m_uid && m_name == rhs.m_name; }
friend std::string DebugPrint(Author const & author)
{
std::ostringstream os;
@@ -122,8 +151,9 @@ struct Text
Text() = default;
Text(std::string const & text, uint8_t const lang) : m_text(text), m_lang(lang) {}
- bool operator==(Text const & rhs) const { return m_lang == rhs.m_lang && m_text == rhs.m_text; }
+ DECLARE_VISITOR(visitor(m_lang, "lang"), visitor(m_text, "text"));
+ bool operator==(Text const & rhs) const { return m_lang == rhs.m_lang && m_text == rhs.m_text; }
friend std::string DebugPrint(Text const & text)
{
std::ostringstream os;
@@ -147,24 +177,16 @@ struct Review
{
}
+ DECLARE_VISITOR(visitor(m_id, "id"), visitor(m_text, "text"), visitor(m_author, "author"),
+ visitor.VisitRating(m_rating, "rating"), visitor(m_sentiment, "sentiment"),
+ visitor(m_time, "time"))
+
bool operator==(Review const & rhs) const
{
return m_id == rhs.m_id && m_text == rhs.m_text && m_author == rhs.m_author &&
m_rating == rhs.m_rating && m_sentiment == rhs.m_sentiment && m_time == rhs.m_time;
}
- uint32_t DaysSinceEpoch() const
- {
- auto const hours = std::chrono::duration_cast<std::chrono::hours>(m_time.time_since_epoch());
- return static_cast<uint32_t>(hours.count()) / 24;
- }
-
- void SetDaysSinceEpoch(uint32_t days)
- {
- auto const hours = std::chrono::hours(days * 24);
- m_time = Time(hours);
- }
-
friend std::string DebugPrint(Review const & review)
{
std::ostringstream os;
@@ -174,7 +196,7 @@ struct Review
os << "author:" << DebugPrint(review.m_author) << ", ";
os << "rating:" << review.m_rating << ", ";
os << "sentiment:" << DebugPrint(review.m_sentiment) << ", ";
- os << "days since epoch:" << review.DaysSinceEpoch() << " ]";
+ os << "days since epoch:" << ToDaysSinceEpoch(review.m_time) << " ]";
return os.str();
}
@@ -196,6 +218,8 @@ struct Attribute
{
}
+ DECLARE_VISITOR(visitor(m_key, "key"), visitor(m_value, "value"))
+
bool operator==(Attribute const & rhs) const
{
return m_key == rhs.m_key && m_value == rhs.m_value;
@@ -221,7 +245,11 @@ struct UGC
{
}
- bool operator==(UGC const & rhs) const {
+ DECLARE_VISITOR(visitor(m_rating, "rating"), visitor(m_reviews, "review"),
+ visitor(m_attributes, "attributes"))
+
+ bool operator==(UGC const & rhs) const
+ {
return m_rating == rhs.m_rating && m_reviews == rhs.m_reviews &&
m_attributes == rhs.m_attributes;
}
@@ -274,3 +302,5 @@ struct UGCUpdate
ReviewFeedback m_feedbacks;
};
} // namespace ugc
+
+#undef DECLARE_VISITOR
diff --git a/ugc/ugc_tests/serdes_tests.cpp b/ugc/ugc_tests/serdes_tests.cpp
index 66638655a3..5687570f32 100644
--- a/ugc/ugc_tests/serdes_tests.cpp
+++ b/ugc/ugc_tests/serdes_tests.cpp
@@ -29,6 +29,7 @@ Rating GetTestRating()
}
MemWriter<Buffer> MakeSink(Buffer & buffer) { return MemWriter<Buffer>(buffer); }
+
ReaderSource<MemReader> MakeSource(Buffer const & buffer)
{
MemReader reader(buffer.data(), buffer.size());
@@ -37,7 +38,7 @@ ReaderSource<MemReader> MakeSource(Buffer const & buffer)
UNIT_TEST(SerDes_Rating)
{
- auto const expectedRating = GetTestRating();
+ auto expectedRating = GetTestRating();
TEST_EQUAL(expectedRating, expectedRating, ());
HeaderV0 header;
@@ -46,14 +47,16 @@ UNIT_TEST(SerDes_Rating)
{
auto sink = MakeSink(buffer);
- Ser(sink, header)(expectedRating);
+ Ser ser(sink, header);
+ ser(expectedRating);
}
Rating actualRating({} /* ratings */, {} /* aggValue */);
{
auto source = MakeSource(buffer);
- Des(source, header)(actualRating);
+ Des des(source, header);
+ des(actualRating);
}
TEST_EQUAL(expectedRating, actualRating, ());
@@ -61,7 +64,7 @@ UNIT_TEST(SerDes_Rating)
UNIT_TEST(SerDes_UGC)
{
- auto const expectedUGC = Api::MakeTestUGC1();
+ auto expectedUGC = Api::MakeTestUGC1();
TEST_EQUAL(expectedUGC, expectedUGC, ());
HeaderV0 header;
@@ -70,13 +73,15 @@ UNIT_TEST(SerDes_UGC)
{
auto sink = MakeSink(buffer);
- Ser(sink, header)(expectedUGC);
+ Ser ser(sink, header);
+ ser(expectedUGC);
}
UGC actualUGC({} /* rating */, {} /* reviews */, {} /* attributes */);
{
auto source = MakeSource(buffer);
- Des(source, header)(actualUGC);
+ Des des(source, header);
+ des(actualUGC);
}
TEST_EQUAL(expectedUGC, actualUGC, ());