Add .visit(many, callbacks) method to MTP types.

This commit is contained in:
John Preston 2018-06-12 22:29:59 +03:00
parent 6776d88688
commit 5a9d1a3fce
2 changed files with 67 additions and 28 deletions

View file

@ -84,6 +84,7 @@ factories = '';
flagOperators = '';
methods = '';
inlineMethods = '';
visitorMethods = '';
textSerializeInit = '';
textSerializeMethods = '';
forwards = '';
@ -577,6 +578,7 @@ for restype in typesList:
switchLines = '';
friendDecl = '';
getters = '';
visitor = '';
reader = '';
writer = '';
sizeList = [];
@ -594,9 +596,14 @@ for restype in typesList:
trivialConditions = data[7];
dataText = '';
dataText += '\nclass MTPD' + name + ' : public MTP::internal::TypeData {\n'; # data class
if (len(prms) > len(trivialConditions)):
withData = 1;
dataText += '\nclass MTPD' + name + ' : public MTP::internal::TypeData {\n'; # data class
else:
dataText += '\nclass MTPD' + name + ' {\n'; # empty data class for visitors
dataText += 'public:\n';
dataText += '\ttemplate <typename Other>\n';
dataText += '\tstatic constexpr bool Is() { return std::is_same_v<std::decay_t<Other>, MTPD' + name + '>; };\n\n';
sizeList = [];
creatorParams = [];
creatorParamsList = [];
@ -626,13 +633,15 @@ for restype in typesList:
dataText += '\tbool has_' + paramName + '() const { return v' + hasFlags + '.v & Flag::f_' + paramName + '; }\n';
dataText += '\n';
dataText += '\tMTPD' + name + '() = default;\n'; # default constructor
switchLines += '\t\tcase mtpc_' + name + ': '; # for by-type-id type constructor
if (len(prms) > len(trivialConditions)):
switchLines += 'setData(new MTPD' + name + '()); ';
withData = 1;
switchLines += '\tcase mtpc_' + name + ': '; # for by-type-id type constructor
getters += '\tconst MTPD' + name + ' &c_' + name + '() const;\n'; # const getter
visitor += '\tcase mtpc_' + name + ': return VisitData(c_' + name + '(), std::forward<Callback>(callback), std::forward<Callbacks>(callbacks)...);\n';
forwards += 'class MTPD' + name + ';\n'; # data class forward declaration
if (len(prms) > len(trivialConditions)):
dataText += '\tMTPD' + name + '() = default;\n'; # default constructor
switchLines += 'setData(new MTPD' + name + '()); ';
getters += '\tconst MTPD' + name + ' &c_' + name + '() const;\n'; # const getter
constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n';
if (withType):
constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n';
@ -662,8 +671,8 @@ for restype in typesList:
creatorParamsList.append('_' + paramName);
prmsInit.append('v' + paramName + '(_' + paramName + ')');
if (withType):
readText += '\t\t';
writeText += '\t\t';
readText += '\t';
writeText += '\t';
if (paramName in conditions):
readText += '\tif (v->has_' + paramName + '()) { v->v' + paramName + '.read(from, end); } else { v->v' + paramName + ' = MTP' + paramType + '(); }\n';
writeText += '\tif (v.has_' + paramName + '()) v.v' + paramName + '.write(to);\n';
@ -673,8 +682,6 @@ for restype in typesList:
writeText += '\tv.v' + paramName + '.write(to);\n';
sizeList.append('v.v' + paramName + '.innerLength()');
forwards += 'class MTPD' + name + ';\n'; # data class forward declaration
dataText += ', '.join(prmsStr) + ');\n';
constructsBodies += 'MTPD' + name + '::MTPD' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n';
@ -685,20 +692,26 @@ for restype in typesList:
continue;
paramType = prms[paramName];
dataText += '\tMTP' + paramType + ' v' + paramName + ';\n';
sizeCases += '\t\tcase mtpc_' + name + ': {\n';
sizeCases += '\t\t\tconst MTPD' + name + ' &v(c_' + name + '());\n';
sizeCases += '\t\t\treturn ' + ' + '.join(sizeList) + ';\n';
sizeCases += '\t\t}\n';
sizeCases += '\tcase mtpc_' + name + ': {\n';
sizeCases += '\t\tconst MTPD' + name + ' &v(c_' + name + '());\n';
sizeCases += '\t\treturn ' + ' + '.join(sizeList) + ';\n';
sizeCases += '\t}\n';
sizeFast = '\tconst MTPD' + name + ' &v(c_' + name + '());\n\treturn ' + ' + '.join(sizeList) + ';\n';
newFast = 'new MTPD' + name + '()';
else:
constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n';
if (withType):
constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n';
constructsBodies += '\tstatic const MTPD' + name + ' result;\n';
constructsBodies += '\treturn result;\n';
constructsBodies += '}\n';
sizeFast = '\treturn 0;\n';
switchLines += 'break;\n';
dataText += '};\n'; # class ending
if (len(prms) > len(trivialConditions)):
dataTexts += dataText; # add data class
dataTexts += dataText; # add data class
if (not friendDecl):
friendDecl += '\tfriend class MTP::internal::TypeCreator;\n';
@ -717,18 +730,18 @@ for restype in typesList:
creatorsBodies += '}\n';
if (withType):
reader += '\t\tcase mtpc_' + name + ': _type = cons; '; # read switch line
reader += '\tcase mtpc_' + name + ': _type = cons; '; # read switch line
if (len(prms) > len(trivialConditions)):
reader += '{\n';
reader += '\t\t\tauto v = new MTPD' + name + '();\n';
reader += '\t\t\tsetData(v);\n';
reader += '\t\tauto v = new MTPD' + name + '();\n';
reader += '\t\tsetData(v);\n';
reader += readText;
reader += '\t\t} break;\n';
reader += '\t} break;\n';
writer += '\t\tcase mtpc_' + name + ': {\n'; # write switch line
writer += '\t\t\tauto &v = c_' + name + '();\n';
writer += '\tcase mtpc_' + name + ': {\n'; # write switch line
writer += '\t\tauto &v = c_' + name + '();\n';
writer += writeText;
writer += '\t\t} break;\n';
writer += '\t} break;\n';
else:
reader += 'break;\n';
else:
@ -737,7 +750,7 @@ for restype in typesList:
reader += '\tsetData(v);\n';
reader += readText;
writer += '\tauto &v = c_' + name + '();\n';
writer += '\tconst auto &v = c_' + name + '();\n';
writer += writeText;
forwards += '\n';
@ -756,6 +769,17 @@ for restype in typesList:
if (withData):
typesText += getters;
if (withType):
typesText += '\n';
typesText += '\ttemplate <typename Callback, typename ...Callbacks>\n';
typesText += '\tdecltype(auto) visit(Callback &&callback, Callbacks &&...callbacks) const;\n';
visitorMethods += 'template <typename Callback, typename ...Callbacks>\n';
visitorMethods += 'decltype(auto) MTP' + restype + '::visit(Callback &&callback, Callbacks &&...callbacks) const {\n';
visitorMethods += '\tswitch (_type) {\n';
visitorMethods += visitor;
visitorMethods += '\t}\n';
visitorMethods += '\tUnexpected("Type in MTP' + restype + '::visit.");\n';
visitorMethods += '}\n\n';
typesText += '\n\tuint32 innerLength() const;\n'; # size method
methods += '\nuint32 MTP' + restype + '::innerLength() const {\n';
@ -788,7 +812,7 @@ for restype in typesList:
if (withType):
methods += '\tswitch (cons) {\n'
methods += reader;
methods += '\t\tdefault: throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\tdefault: throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\t}\n';
else:
methods += reader;
@ -814,7 +838,7 @@ for restype in typesList:
methods += ' {\n';
methods += '\tswitch (type) {\n'; # type id check
methods += switchLines;
methods += '\t\tdefault: throw mtpErrorBadTypeId(type, "MTP' + restype + '");\n\t}\n';
methods += '\tdefault: throw mtpErrorBadTypeId(type, "MTP' + restype + '");\n\t}\n';
methods += '}\n'; # by-type-id constructor end
if (withData):
@ -953,6 +977,8 @@ enum {\n\
' + funcsText + '\n\
// Template methods definition\n\
' + inlineMethods + '\n\
// Visitor definition\n\
' + visitorMethods + '\n\
// Flag operators definition\n\
' + flagOperators + '\n\
// Factory methods declaration\n\

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QVector>
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <rpl/details/callable.h>
#include "core/basic_types.h"
#include "base/flags.h"
#include "base/bytes.h"
@ -229,6 +230,18 @@ protected:
return static_cast<const DataType &>(*_data);
}
template <typename Data, typename Callback, typename ...Callbacks>
static decltype(auto) VisitData(
const Data &data,
Callback &&callback,
Callbacks &&...callbacks) {
if constexpr (rpl::details::is_callable_plain_v<Callback, Data>) {
return std::forward<Callback>(callback)(data);
} else {
return VisitData(data, std::forward<Callbacks>(callbacks)...);
}
}
private:
void incrementCounter() {
if (_data) {