Move a lot of code from scheme.h to scheme.cpp.

This commit is contained in:
John Preston 2017-08-12 10:17:33 +03:00
parent 1207ddb2ea
commit c8810f87b9
19 changed files with 447 additions and 387 deletions

View File

@ -158,7 +158,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
}
if (d.vset.type() == mtpc_stickerSet) {
auto &s = d.vset.c_stickerSet();
_setTitle = stickerSetTitle(s);
_setTitle = Stickers::GetSetTitle(s);
_setShortName = qs(s.vshort_name);
_setId = s.vid.v;
_setAccess = s.vaccess_hash.v;

View File

@ -524,7 +524,7 @@ void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVect
if (set) {
auto it = sets.find(set->vid.v);
auto title = stickerSetTitle(*set);
auto title = GetSetTitle(*set);
if (it == sets.cend()) {
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded;
if (unreadMap.contains(set->vid.v)) {
@ -684,7 +684,7 @@ std::vector<gsl::not_null<EmojiPtr>> GetEmojiListFromSet(gsl::not_null<DocumentD
Set *FeedSet(const MTPDstickerSet &set) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(set.vid.v);
auto title = stickerSetTitle(set);
auto title = GetSetTitle(set);
auto flags = MTPDstickerSet::Flags(0);
if (it == sets.cend()) {
it = sets.insert(set.vid.v, Stickers::Set(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_ClientFlag::f_not_loaded));
@ -807,6 +807,14 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
return set;
}
QString GetSetTitle(const MTPDstickerSet &s) {
auto title = qs(s.vtitle);
if ((s.vflags.v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
return lang(lng_stickers_default_set);
}
return title;
}
namespace internal {
FeaturedReader::FeaturedReader(QObject *parent) : QObject(parent)

View File

@ -45,6 +45,8 @@ std::vector<gsl::not_null<EmojiPtr>> GetEmojiListFromSet(gsl::not_null<DocumentD
Set *FeedSet(const MTPDstickerSet &data);
Set *FeedSetFull(const MTPmessages_StickerSet &data);
QString GetSetTitle(const MTPDstickerSet &s);
namespace internal {
class FeaturedReader : public QObject, private MTP::Sender {

View File

@ -83,6 +83,9 @@ funcsText = '';
typesText = '';
dataTexts = '';
creatorProxyText = '';
factories = '';
flagOperators = '';
methods = '';
inlineMethods = '';
textSerializeInit = '';
textSerializeMethods = '';
@ -297,6 +300,7 @@ with open(input_file) as f:
continue;
if funcsNow:
methodBodies = ''
if (isTemplate != ''):
funcsText += '\ntemplate <typename TQueryType>';
funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class
@ -318,7 +322,7 @@ with open(input_file) as f:
funcsText += '\n';
funcsText += '\t\tMAX_FIELD = (1 << ' + str(maxbit) + '),\n';
funcsText += '\t};\n';
funcsText += '\tQ_DECLARE_FLAGS(Flags, Flag);\n';
funcsText += '\tusing Flags = QFlags<Flag>;\n';
funcsText += '\tfriend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }\n';
funcsText += '\n';
if (len(conditions)):
@ -352,7 +356,12 @@ with open(input_file) as f:
funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n\t}\n';
funcsText += '\n';
funcsText += '\tuint32 innerLength() const {\n'; # count size
funcsText += '\tuint32 innerLength() const;\n'; # count size
if (isTemplate != ''):
methodBodies += 'template <typename TQueryType>\n'
methodBodies += 'uint32 MTP' + name + '<TQueryType>::innerLength() const {\n';
else:
methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n';
size = [];
for k in prmsList:
v = prms[k];
@ -363,56 +372,56 @@ with open(input_file) as f:
size.append('v' + k + '.innerLength()');
if (not len(size)):
size.append('0');
funcsText += '\t\treturn ' + ' + '.join(size) + ';\n';
funcsText += '\t}\n';
methodBodies += '\treturn ' + ' + '.join(size) + ';\n';
methodBodies += '}\n';
funcsText += '\tmtpTypeId type() const {\n\t\treturn mtpc_' + name + ';\n\t}\n'; # type id
funcsText += '\tvoid read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ') {\n'; # read method
funcsText += '\tvoid read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ');\n'; # read method
if (isTemplate != ''):
methodBodies += 'template <typename TQueryType>\n'
methodBodies += 'void MTP' + name + '<TQueryType>::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
else:
methodBodies += 'void MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
for k in prmsList:
v = prms[k];
if (k in conditionsList):
if (not k in trivialConditions):
funcsText += '\t\tif (has_' + k + '()) { v' + k + '.read(from, end); } else { v' + k + ' = MTP' + v + '(); }\n';
methodBodies += '\tif (has_' + k + '()) { v' + k + '.read(from, end); } else { v' + k + ' = MTP' + v + '(); }\n';
else:
funcsText += '\t\tv' + k + '.read(from, end);\n';
funcsText += '\t}\n';
methodBodies += '\tv' + k + '.read(from, end);\n';
methodBodies += '}\n';
funcsText += '\tvoid write(mtpBuffer &to) const {\n'; # write method
funcsText += '\tvoid write(mtpBuffer &to) const;\n'; # write method
if (isTemplate != ''):
methodBodies += 'template <typename TQueryType>\n'
methodBodies += 'void MTP' + name + '<TQueryType>::write(mtpBuffer &to) const {\n';
else:
methodBodies += 'void MTP' + name + '::write(mtpBuffer &to) const {\n';
for k in prmsList:
v = prms[k];
if (k in conditionsList):
if (not k in trivialConditions):
funcsText += '\t\tif (has_' + k + '()) v' + k + '.write(to);\n';
methodBodies += '\tif (has_' + k + '()) v' + k + '.write(to);\n';
else:
funcsText += '\t\tv' + k + '.write(to);\n';
funcsText += '\t}\n';
methodBodies += '\tv' + k + '.write(to);\n';
methodBodies += '}\n';
if (isTemplate != ''):
funcsText += '\n\tusing ResponseType = typename TQueryType::ResponseType;\n';
inlineMethods += methodBodies;
else:
funcsText += '\n\tusing ResponseType = MTP' + resType + ';\n'; # method return type
methods += methodBodies;
funcsText += '};\n'; # class ending
if (len(conditionsList)):
funcsText += 'Q_DECLARE_OPERATORS_FOR_FLAGS(MTP' + name + '::Flags)\n\n';
if (isTemplate != ''):
funcsText += 'template <typename TQueryType>\n';
funcsText += 'class MTP' + Name + ' : public MTPBoxed<MTP' + name + '<TQueryType> > {\n';
funcsText += 'public:\n';
funcsText += '\tMTP' + Name + '() = default;\n';
funcsText += '\tMTP' + Name + '(const MTP' + name + '<TQueryType> &v) : MTPBoxed<MTP' + name + '<TQueryType> >(v) {\n\t}\n';
if (len(prms) > len(trivialConditions)):
funcsText += '\tMTP' + Name + '(' + ', '.join(prmsStr) + ') : MTPBoxed<MTP' + name + '<TQueryType> >(MTP' + name + '<TQueryType>(' + ', '.join(prmsNames) + ')) {\n\t}\n';
funcsText += '};\n';
funcsText += 'using MTP' + Name + ' = MTPBoxed<MTP' + name + '<TQueryType>>;\n';
else:
funcsText += 'class MTP' + Name + ' : public MTPBoxed<MTP' + name + '> {\n';
funcsText += 'public:\n';
funcsText += '\tMTP' + Name + '() = default;\n';
funcsText += '\tMTP' + Name + '(const MTP' + name + ' &v) : MTPBoxed<MTP' + name + '>(v) {\n\t}\n';
if (len(prms) > len(trivialConditions)):
funcsText += '\tMTP' + Name + '(' + ', '.join(prmsStr) + ') : MTPBoxed<MTP' + name + '>(MTP' + name + '(' + ', '.join(prmsNames) + ')) {\n\t}\n';
funcsText += '};\n';
funcsText += 'using MTP' + Name + ' = MTPBoxed<MTP' + name + '>;\n';
funcs = funcs + 1;
if (not restype in funcsDict):
@ -545,9 +554,11 @@ for restype in typesList:
v = typesDict[restype];
resType = TypesDict[restype];
withData = 0;
creatorsText = '';
creatorsDeclarations = '';
creatorsBodies = '';
flagDeclarations = '';
constructsText = '';
constructsInline = '';
constructsBodies = '';
forwards += 'class MTP' + restype + ';\n';
forwTypedefs += 'using MTP' + resType + ' = MTPBoxed<MTP' + restype + '>;\n';
@ -594,7 +605,7 @@ for restype in typesList:
dataText += '\n';
dataText += '\t\tMAX_FIELD = (1 << ' + str(maxbit) + '),\n';
dataText += '\t};\n';
dataText += '\tQ_DECLARE_FLAGS(Flags, Flag);\n';
dataText += '\tusing Flags = QFlags<Flag>;\n';
dataText += '\tfriend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }\n';
dataText += '\n';
if (len(conditions)):
@ -612,17 +623,17 @@ for restype in typesList:
withData = 1;
getters += '\tconst MTPD' + name + ' &c_' + name + '() const;\n'; # const getter
constructsInline += 'inline const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n';
constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n';
if (withType):
constructsInline += '\tt_assert(_type == mtpc_' + name + ');\n';
constructsInline += '\treturn queryData<MTPD' + name + '>();\n';
constructsInline += '}\n';
constructsBodies += '\tt_assert(_type == mtpc_' + name + ');\n';
constructsBodies += '\treturn queryData<MTPD' + name + '>();\n';
constructsBodies += '}\n';
constructsText += '\texplicit MTP' + restype + '(const MTPD' + name + ' *data);\n'; # by-data type constructor
constructsInline += 'inline MTP' + restype + '::MTP' + restype + '(const MTPD' + name + ' *data) : TypeDataOwner(data)';
constructsBodies += 'MTP' + restype + '::MTP' + restype + '(const MTPD' + name + ' *data) : TypeDataOwner(data)';
if (withType):
constructsInline += ', _type(mtpc_' + name + ')';
constructsInline += ' {\n}\n';
constructsBodies += ', _type(mtpc_' + name + ')';
constructsBodies += ' {\n}\n';
dataText += '\tMTPD' + name + '('; # params constructor
prmsStr = [];
@ -689,10 +700,11 @@ for restype in typesList:
creatorProxyText += '\t\treturn MTP' + restype + '();\n';
creatorProxyText += '\t}\n';
if (len(conditionsList)):
creatorsText += 'Q_DECLARE_OPERATORS_FOR_FLAGS(MTPD' + name + '::Flags)\n';
creatorsText += 'inline MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ') {\n';
creatorsText += '\treturn MTP::internal::TypeCreator::new_' + name + '(' + ', '.join(creatorParamsList) + ');\n';
creatorsText += '}\n';
flagDeclarations += 'Q_DECLARE_OPERATORS_FOR_FLAGS(MTPD' + name + '::Flags)\n';
creatorsDeclarations += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ');\n';
creatorsBodies += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ') {\n';
creatorsBodies += '\treturn MTP::internal::TypeCreator::new_' + name + '(' + ', '.join(creatorParamsList) + ');\n';
creatorsBodies += '}\n';
if (withType):
reader += '\t\tcase mtpc_' + name + ': _type = cons; '; # read switch line
@ -732,10 +744,10 @@ for restype in typesList:
inits.append('TypeDataOwner(' + newFast + ')');
if (withData and not withType):
typesText += ';\n';
inlineMethods += '\ninline MTP' + restype + '::MTP' + restype + '()';
methods += '\nMTP' + restype + '::MTP' + restype + '()';
if (inits):
inlineMethods += ' : ' + ', '.join(inits);
inlineMethods += ' {\n}\n';
methods += ' : ' + ', '.join(inits);
methods += ' {\n}\n';
else:
if (inits):
typesText += ' : ' + ', '.join(inits);
@ -745,68 +757,68 @@ for restype in typesList:
typesText += getters;
typesText += '\n\tuint32 innerLength() const;\n'; # size method
inlineMethods += '\ninline uint32 MTP' + restype + '::innerLength() const {\n';
methods += '\nuint32 MTP' + restype + '::innerLength() const {\n';
if (withType and sizeCases):
inlineMethods += '\tswitch (_type) {\n';
inlineMethods += sizeCases;
inlineMethods += '\t}\n';
inlineMethods += '\treturn 0;\n';
methods += '\tswitch (_type) {\n';
methods += sizeCases;
methods += '\t}\n';
methods += '\treturn 0;\n';
else:
inlineMethods += sizeFast;
inlineMethods += '}\n';
methods += sizeFast;
methods += '}\n';
typesText += '\tmtpTypeId type() const;\n'; # type id method
inlineMethods += 'inline mtpTypeId MTP' + restype + '::type() const {\n';
methods += 'mtpTypeId MTP' + restype + '::type() const {\n';
if (withType):
inlineMethods += '\tt_assert(_type != 0);\n';
inlineMethods += '\treturn _type;\n';
methods += '\tt_assert(_type != 0);\n';
methods += '\treturn _type;\n';
else:
inlineMethods += '\treturn mtpc_' + v[0][0] + ';\n';
inlineMethods += '}\n';
methods += '\treturn mtpc_' + v[0][0] + ';\n';
methods += '}\n';
typesText += '\tvoid read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; # read method
if (not withType):
typesText += ' = mtpc_' + name;
typesText += ');\n';
inlineMethods += 'inline void MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
methods += 'void MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
if (withData):
if not (withType):
inlineMethods += '\tif (cons != mtpc_' + v[0][0] + ') throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\tif (cons != mtpc_' + v[0][0] + ') throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
if (withType):
inlineMethods += '\tswitch (cons) {\n'
inlineMethods += reader;
inlineMethods += '\t\tdefault: throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
inlineMethods += '\t}\n';
methods += '\tswitch (cons) {\n'
methods += reader;
methods += '\t\tdefault: throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\t}\n';
else:
inlineMethods += reader;
inlineMethods += '}\n';
methods += reader;
methods += '}\n';
typesText += '\tvoid write(mtpBuffer &to) const;\n'; # write method
inlineMethods += 'inline void MTP' + restype + '::write(mtpBuffer &to) const {\n';
methods += 'void MTP' + restype + '::write(mtpBuffer &to) const {\n';
if (withType and writer != ''):
inlineMethods += '\tswitch (_type) {\n';
inlineMethods += writer;
inlineMethods += '\t}\n';
methods += '\tswitch (_type) {\n';
methods += writer;
methods += '\t}\n';
else:
inlineMethods += writer;
inlineMethods += '}\n';
methods += writer;
methods += '}\n';
typesText += '\n\tusing ResponseType = void;\n'; # no response types declared
typesText += '\nprivate:\n'; # private constructors
if (withType): # by-type-id constructor
typesText += '\texplicit MTP' + restype + '(mtpTypeId type);\n';
inlineMethods += 'inline MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : ';
inlineMethods += '_type(type)';
inlineMethods += ' {\n';
inlineMethods += '\tswitch (type) {\n'; # type id check
inlineMethods += switchLines;
inlineMethods += '\t\tdefault: throw mtpErrorBadTypeId(type, "MTP' + restype + '");\n\t}\n';
inlineMethods += '}\n'; # by-type-id constructor end
methods += 'MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : ';
methods += '_type(type)';
methods += ' {\n';
methods += '\tswitch (type) {\n'; # type id check
methods += switchLines;
methods += '\t\tdefault: throw mtpErrorBadTypeId(type, "MTP' + restype + '");\n\t}\n';
methods += '}\n'; # by-type-id constructor end
if (withData):
typesText += constructsText;
inlineMethods += constructsInline;
methods += constructsBodies;
if (friendDecl):
typesText += '\n' + friendDecl;
@ -816,9 +828,13 @@ for restype in typesList:
typesText += '};\n'; # type class ended
inlineMethods += creatorsText;
flagOperators += flagDeclarations;
factories += creatorsDeclarations;
methods += creatorsBodies;
typesText += 'using MTP' + resType + ' = MTPBoxed<MTP' + restype + '>;\n'; # boxed type definition
flagOperators += '\n'
for childName in parentFlagsList:
parentName = parentFlags[childName];
for flag in parentFlagsCheck[childName]:
@ -836,8 +852,8 @@ for childName in parentFlagsList:
error
else:
parentFlagsCheck[parentName][flag] = parentFlagsCheck[childName][flag];
inlineMethods += 'inline ' + parentName + '::Flags mtpCastFlags(' + childName + '::Flags flags) { return ' + parentName + '::Flags(QFlag(flags)); }\n';
inlineMethods += 'inline ' + parentName + '::Flags mtpCastFlags(MTPflags<' + childName + '::Flags> flags) { return mtpCastFlags(flags.v); }\n';
flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(' + childName + '::Flags flags) { return ' + parentName + '::Flags(QFlag(flags)); }\n';
flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(MTPflags<' + childName + '::Flags> flags) { return mtpCastFlags(flags.v); }\n';
# manual types added here
textSerializeMethods += '\
@ -946,20 +962,12 @@ enum {\n\
' + dataTexts + '\n\
// RPC methods\n\
' + funcsText + '\n\
// Creator proxy class definition\n\
namespace MTP {\n\
namespace internal {\n\
\n\
class TypeCreator {\n\
public:\n\
' + creatorProxyText + '\n\
};\n\
\n\
} // namespace internal\n\
} // namespace MTP\n\
\n\
// Inline methods definition\n\
// Template methods definition\n\
' + inlineMethods + '\n\
// Flag operators definition\n\
' + flagOperators + '\n\
// Factory methods declaration\n\
' + factories + '\n\
// Human-readable text serialization\n\
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n'
@ -986,6 +994,21 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org\n\
*/\n\
#include "scheme.h"\n\
\n\
// Creator proxy class definition\n\
namespace MTP {\n\
namespace internal {\n\
\n\
class TypeCreator {\n\
public:\n\
' + creatorProxyText + '\n\
};\n\
\n\
} // namespace internal\n\
} // namespace MTP\n\
\n\
// Methods definition\n\
' + methods + '\n\
\n\
using Types = QVector<mtpTypeId>;\n\
using StagesFlags = QVector<int32>;\n\
\n\

View File

@ -84,7 +84,7 @@ private:
Over = 0x01,
DeleteOver = 0x02,
};
Q_DECLARE_FLAGS(StateFlags, StateFlag);
using StateFlags = QFlags<StateFlag>;
StateFlags _state;
friend inline StateFlags operator~(StateFlag flag) {
return ~StateFlags(flag);

View File

@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "core/basic_types.h"
#include "structs.h"
#include "mtproto/core_types.h"
class FileLoader;

View File

@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "core/basic_types.h"
#include "structs.h"
#include "mtproto/core_types.h"
#include "history/history_location_manager.h"
namespace InlineBots {

View File

@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "data/data_drafts.h"
#include "ui/widgets/dropdown_menu.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "observer_peer.h"
#include "apiwrap.h"
#include "dialogs/dialogs_widget.h"
@ -5218,7 +5219,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(s.vid.v);
if (it == sets.cend()) {
it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v | MTPDstickerSet::Flag::f_installed));
it = sets.insert(s.vid.v, Stickers::Set(s.vid.v, s.vaccess_hash.v, Stickers::GetSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v | MTPDstickerSet::Flag::f_installed));
} else {
it->flags |= MTPDstickerSet::Flag::f_installed;
if (it->flags & MTPDstickerSet::Flag::f_archived) {

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/auth_key.h"
#include "mtproto/dc_options.h"
#include "core/single_timer.h"

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/dc_options.h"
namespace MTP {

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/connection_tcp.h"
namespace MTP {

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/connection_abstract.h"
namespace MTP {

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/auth_key.h"
#include "mtproto/connection_abstract.h"

View File

@ -22,10 +22,131 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "zlib.h"
#include "lang/lang_keys.h"
uint32 MTPstring::innerLength() const {
uint32 l = v.length();
if (l < 254) {
l += 1;
} else {
l += 4;
}
uint32 d = l & 0x03;
if (d) l += (4 - d);
return l;
}
QString mtpWrapNumber(float64 number) {
return QString::number(number);
void MTPstring::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_string) throw mtpErrorUnexpected(cons, "MTPstring");
uint32 l;
const uchar *buf = (const uchar*)from;
if (buf[0] == 254) {
l = (uint32)buf[1] + ((uint32)buf[2] << 8) + ((uint32)buf[3] << 16);
buf += 4;
from += ((l + 4) >> 2) + (((l + 4) & 0x03) ? 1 : 0);
} else {
l = (uint32)buf[0];
++buf;
from += ((l + 1) >> 2) + (((l + 1) & 0x03) ? 1 : 0);
}
if (from > end) throw mtpErrorInsufficient();
v = QByteArray(reinterpret_cast<const char*>(buf), l);
}
void MTPstring::write(mtpBuffer &to) const {
uint32 l = v.length(), s = l + ((l < 254) ? 1 : 4), was = to.size();
if (s & 0x03) {
s += 4;
}
s >>= 2;
to.resize(was + s);
char *buf = (char*)&to[was];
if (l < 254) {
uchar sl = (uchar)l;
*(buf++) = *(char*)(&sl);
} else {
*(buf++) = (char)254;
*(buf++) = (char)(l & 0xFF);
*(buf++) = (char)((l >> 8) & 0xFF);
*(buf++) = (char)((l >> 16) & 0xFF);
}
memcpy(buf, v.constData(), l);
}
uint32 mtpRequest::innerLength() const { // for template MTP requests and MTPBoxed instanciation
mtpRequestData *value = data();
if (!value || value->size() < 9) return 0;
return value->at(7);
}
void mtpRequest::write(mtpBuffer &to) const {
mtpRequestData *value = data();
if (!value || value->size() < 9) return;
uint32 was = to.size(), s = innerLength() / sizeof(mtpPrime);
to.resize(was + s);
memcpy(to.data() + was, value->constData() + 8, s * sizeof(mtpPrime));
}
bool mtpRequestData::isSentContainer(const mtpRequest &request) { // "request-like" wrap for msgIds vector
if (request->size() < 9) return false;
return (!request->msDate && !(*request)[6]); // msDate = 0, seqNo = 0
}
bool mtpRequestData::isStateRequest(const mtpRequest &request) {
if (request->size() < 9) return false;
return (mtpTypeId((*request)[8]) == mtpc_msgs_state_req);
}
bool mtpRequestData::needAckByType(mtpTypeId type) {
switch (type) {
case mtpc_msg_container:
case mtpc_msgs_ack:
case mtpc_http_wait:
case mtpc_bad_msg_notification:
case mtpc_msgs_all_info:
case mtpc_msgs_state_info:
case mtpc_msg_detailed_info:
case mtpc_msg_new_detailed_info:
return false;
}
return true;
}
mtpRequest mtpRequestData::prepare(uint32 requestSize, uint32 maxSize) {
if (!maxSize) maxSize = requestSize;
mtpRequest result(new mtpRequestData(true));
result->reserve(8 + maxSize + _padding(maxSize)); // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
result->resize(7);
result->push_back(requestSize << 2);
return result;
}
void mtpRequestData::padding(mtpRequest &request) {
if (request->size() < 9) return;
uint32 requestSize = (request.innerLength() >> 2), padding = _padding(requestSize), fullSize = 8 + requestSize + padding; // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
if (uint32(request->size()) != fullSize) {
request->resize(fullSize);
if (padding) {
memset_rand(request->data() + (fullSize - padding), padding * sizeof(mtpPrime));
}
}
}
uint32 mtpRequestData::_padding(uint32 requestSize) {
#ifdef TDESKTOP_MTPROTO_OLD
return ((8 + requestSize) & 0x03) ? (4 - ((8 + requestSize) & 0x03)) : 0;
#else // TDESKTOP_MTPROTO_OLD
auto result = ((8 + requestSize) & 0x03) ? (4 - ((8 + requestSize) & 0x03)) : 0;
// At least 12 bytes of random padding.
if (result < 3) {
result += 4;
}
return result;
#endif // TDESKTOP_MTPROTO_OLD
}
void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) {
@ -33,31 +154,31 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case mtpc_int: {
MTPint value;
value.read(from, end, cons);
to.add(mtpWrapNumber(value.v)).add(" [INT]");
to.add(QString::number(value.v)).add(" [INT]");
} break;
case mtpc_long: {
MTPlong value;
value.read(from, end, cons);
to.add(mtpWrapNumber(value.v)).add(" [LONG]");
to.add(QString::number(value.v)).add(" [LONG]");
} break;
case mtpc_int128: {
MTPint128 value;
value.read(from, end, cons);
to.add(mtpWrapNumber(value.h)).add(" * 2^64 + ").add(mtpWrapNumber(value.l)).add(" [INT128]");
to.add(QString::number(value.h)).add(" * 2^64 + ").add(QString::number(value.l)).add(" [INT128]");
} break;
case mtpc_int256: {
MTPint256 value;
value.read(from, end, cons);
to.add(mtpWrapNumber(value.h.h)).add(" * 2^192 + ").add(mtpWrapNumber(value.h.l)).add(" * 2^128 + ").add(mtpWrapNumber(value.l.h)).add(" * 2 ^ 64 + ").add(mtpWrapNumber(value.l.l)).add(" [INT256]");
to.add(QString::number(value.h.h)).add(" * 2^192 + ").add(QString::number(value.h.l)).add(" * 2^128 + ").add(QString::number(value.l.h)).add(" * 2 ^ 64 + ").add(QString::number(value.l.l)).add(" [INT256]");
} break;
case mtpc_double: {
MTPdouble value;
value.read(from, end, cons);
to.add(mtpWrapNumber(value.v)).add(" [DOUBLE]");
to.add(QString::number(value.v)).add(" [DOUBLE]");
} break;
case mtpc_string: {
@ -68,9 +189,9 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
if (str.toUtf8() == strUtf8) {
to.add("\"").add(str.replace('\\', "\\\\").replace('"', "\\\"").replace('\n', "\\n")).add("\" [STRING]");
} else if (strUtf8.size() < 64) {
to.add(Logs::mb(strUtf8.constData(), strUtf8.size()).str()).add(" [").add(mtpWrapNumber(strUtf8.size())).add(" BYTES]");
to.add(Logs::mb(strUtf8.constData(), strUtf8.size()).str()).add(" [").add(QString::number(strUtf8.size())).add(" BYTES]");
} else {
to.add(Logs::mb(strUtf8.constData(), 16).str()).add("... [").add(mtpWrapNumber(strUtf8.size())).add(" BYTES]");
to.add(Logs::mb(strUtf8.constData(), 16).str()).add("... [").add(QString::number(strUtf8.size())).add(" BYTES]");
}
} break;
@ -79,7 +200,7 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
throw Exception("from >= end in vector");
}
int32 cnt = *(from++);
to.add("[ vector<0x").add(mtpWrapNumber(vcons, 16)).add(">");
to.add("[ vector<0x").add(QString::number(vcons, 16)).add(">");
if (cnt) {
to.add("\n").addSpaces(level);
for (int32 i = 0; i < cnt; ++i) {
@ -140,7 +261,7 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
default: {
for (uint32 i = 1; i < mtpLayerMaxSingle; ++i) {
if (cons == mtpLayers[i]) {
to.add("[LAYER").add(mtpWrapNumber(i + 1)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
to.add("[LAYER").add(QString::number(i + 1)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
return;
}
}
@ -149,22 +270,10 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
throw Exception("from >= end in invokeWithLayer");
}
int32 layer = *(from++);
to.add("[LAYER").add(mtpWrapNumber(layer)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
to.add("[LAYER").add(QString::number(layer)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
return;
}
throw Exception(QString("unknown cons 0x%1").arg(cons, 0, 16));
} break;
}
}
const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_flags(0), MTP_vector<MTPKeyboardButtonRow>(0));
const MTPVector<MTPMessageEntity> MTPnullEntities = MTP_vector<MTPMessageEntity>(0);
const MTPMessageFwdHeader MTPnullFwdHeader = MTP_messageFwdHeader(MTP_flags(0), MTPint(), MTPint(), MTPint(), MTPint(), MTPstring());
QString stickerSetTitle(const MTPDstickerSet &s) {
QString title = qs(s.vtitle);
if ((s.vflags.v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
return lang(lng_stickers_default_set);
}
return title;
}

View File

@ -42,8 +42,7 @@ using mtpTypeId = uint32;
class mtpRequestData;
class mtpRequest : public QSharedPointer<mtpRequestData> {
public:
mtpRequest() {
}
mtpRequest() = default;
explicit mtpRequest(mtpRequestData *ptr) : QSharedPointer<mtpRequestData>(ptr) {
}
@ -58,35 +57,17 @@ class mtpRequestData : public mtpBuffer {
public:
// in toSend: = 0 - must send in container, > 0 - can send without container
// in haveSent: = 0 - container with msgIds, > 0 - when was sent
TimeMs msDate;
TimeMs msDate = 0;
mtpRequestId requestId;
mtpRequestId requestId = 0;
mtpRequest after;
bool needsLayer;
bool needsLayer = false;
mtpRequestData(bool/* sure*/) : msDate(0), requestId(0), needsLayer(false) {
mtpRequestData(bool/* sure*/) {
}
static mtpRequest prepare(uint32 requestSize, uint32 maxSize = 0) {
if (!maxSize) maxSize = requestSize;
mtpRequest result(new mtpRequestData(true));
result->reserve(8 + maxSize + _padding(maxSize)); // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
result->resize(7);
result->push_back(requestSize << 2);
return result;
}
static void padding(mtpRequest &request) {
if (request->size() < 9) return;
uint32 requestSize = (request.innerLength() >> 2), padding = _padding(requestSize), fullSize = 8 + requestSize + padding; // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
if (uint32(request->size()) != fullSize) {
request->resize(fullSize);
if (padding) {
memset_rand(request->data() + (fullSize - padding), padding * sizeof(mtpPrime));
}
}
}
static mtpRequest prepare(uint32 requestSize, uint32 maxSize = 0);
static void padding(mtpRequest &request);
static uint32 messageSize(const mtpRequest &request) {
if (request->size() < 9) return 0;
@ -95,41 +76,17 @@ public:
static bool isSentContainer(const mtpRequest &request); // "request-like" wrap for msgIds vector
static bool isStateRequest(const mtpRequest &request);
static bool needAck(const mtpRequest &request);
static bool needAck(const mtpRequest &request) {
if (request->size() < 9) return false;
return mtpRequestData::needAckByType((*request)[8]);
}
static bool needAckByType(mtpTypeId type);
private:
static uint32 _padding(uint32 requestSize) {
#ifdef TDESKTOP_MTPROTO_OLD
return ((8 + requestSize) & 0x03) ? (4 - ((8 + requestSize) & 0x03)) : 0;
#else // TDESKTOP_MTPROTO_OLD
auto result = ((8 + requestSize) & 0x03) ? (4 - ((8 + requestSize) & 0x03)) : 0;
// At least 12 bytes of random padding.
if (result < 3) {
result += 4;
}
return result;
#endif // TDESKTOP_MTPROTO_OLD
}
static uint32 _padding(uint32 requestSize);
};
inline uint32 mtpRequest::innerLength() const { // for template MTP requests and MTPBoxed instanciation
mtpRequestData *value = data();
if (!value || value->size() < 9) return 0;
return value->at(7);
}
inline void mtpRequest::write(mtpBuffer &to) const {
mtpRequestData *value = data();
if (!value || value->size() < 9) return;
uint32 was = to.size(), s = innerLength() / sizeof(mtpPrime);
to.resize(was + s);
memcpy(to.data() + was, value->constData() + 8, s * sizeof(mtpPrime));
}
using mtpPreRequestMap = QMap<mtpRequestId, mtpRequest>;
using mtpRequestMap = QMap<mtpMsgId, mtpRequest>;
using mtpMsgIdsSet = QMap<mtpMsgId, bool>;
@ -152,18 +109,21 @@ class mtpErrorUnexpected : public Exception {
public:
mtpErrorUnexpected(mtpTypeId typeId, const QString &type) : Exception(QString("MTP Unexpected type id #%1 read in %2").arg(uint32(typeId), 0, 16).arg(type), false) { // maybe api changed?..
}
};
class mtpErrorInsufficient : public Exception {
public:
mtpErrorInsufficient() : Exception("MTP Insufficient bytes in input buffer") {
}
};
class mtpErrorBadTypeId : public Exception {
public:
mtpErrorBadTypeId(mtpTypeId typeId, const QString &type) : Exception(QString("MTP Bad type id %1 passed to constructor of %2").arg(typeId).arg(type)) {
}
};
namespace MTP {
@ -228,10 +188,10 @@ protected:
_data = data;
}
// Unsafe cast, type should be checked by the caller.
template <typename DataType>
const DataType &queryData() const {
// Unsafe cast, type should be checked by the caller.
t_assert(_data != nullptr);
Expects(_data != nullptr);
return static_cast<const DataType &>(*_data);
}
@ -319,20 +279,16 @@ static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0])
template <typename bareT>
class MTPBoxed : public bareT {
public:
using bareT::bareT;
MTPBoxed() = default;
MTPBoxed(const MTPBoxed<bareT> &v) = default;
MTPBoxed<bareT> &operator=(const MTPBoxed<bareT> &v) = default;
MTPBoxed(const bareT &v) : bareT(v) {
}
MTPBoxed(const MTPBoxed<bareT> &v) : bareT(v) {
}
MTPBoxed<bareT> &operator=(const bareT &v) {
*((bareT*)this) = v;
return *this;
}
MTPBoxed<bareT> &operator=(const MTPBoxed<bareT> &v) {
*((bareT*)this) = v;
return *this;
}
uint32 innerLength() const {
return sizeof(mtpTypeId) + bareT::innerLength();
@ -631,58 +587,12 @@ class MTPstring {
public:
MTPstring() = default;
uint32 innerLength() const {
uint32 l = v.length();
if (l < 254) {
l += 1;
} else {
l += 4;
}
uint32 d = l & 0x03;
if (d) l += (4 - d);
return l;
}
uint32 innerLength() const;
mtpTypeId type() const {
return mtpc_string;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_string) throw mtpErrorUnexpected(cons, "MTPstring");
uint32 l;
const uchar *buf = (const uchar*)from;
if (buf[0] == 254) {
l = (uint32)buf[1] + ((uint32)buf[2] << 8) + ((uint32)buf[3] << 16);
buf += 4;
from += ((l + 4) >> 2) + (((l + 4) & 0x03) ? 1 : 0);
} else {
l = (uint32)buf[0];
++buf;
from += ((l + 1) >> 2) + (((l + 1) & 0x03) ? 1 : 0);
}
if (from > end) throw mtpErrorInsufficient();
v = QByteArray(reinterpret_cast<const char*>(buf), l);
}
void write(mtpBuffer &to) const {
uint32 l = v.length(), s = l + ((l < 254) ? 1 : 4), was = to.size();
if (s & 0x03) {
s += 4;
}
s >>= 2;
to.resize(was + s);
char *buf = (char*)&to[was];
if (l < 254) {
uchar sl = (uchar)l;
*(buf++) = *(char*)(&sl);
} else {
*(buf++) = (char)254;
*(buf++) = (char)(l & 0xFF);
*(buf++) = (char)((l >> 8) & 0xFF);
*(buf++) = (char)((l >> 16) & 0xFF);
}
memcpy(buf, v.constData(), l);
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string);
void write(mtpBuffer &to) const;
QByteArray v;
@ -832,11 +742,6 @@ inline bool operator!=(const MTPvector<T> &a, const MTPvector<T> &b) {
// Human-readable text serialization
template <typename Type>
QString mtpWrapNumber(Type number, int32 base = 10) {
return QString::number(number, base);
}
struct MTPStringLogger {
MTPStringLogger() : p(new char[MTPDebugBufferSize]), size(0), alloced(MTPDebugBufferSize) {
}
@ -899,141 +804,3 @@ inline QString mtpTextSerialize(const mtpPrime *&from, const mtpPrime *end) {
}
return QString::fromUtf8(to.p, to.size);
}
#include "scheme.h"
inline MTPbool MTP_bool(bool v) {
return v ? MTP_boolTrue() : MTP_boolFalse();
}
inline bool mtpIsTrue(const MTPBool &v) {
return v.type() == mtpc_boolTrue;
}
inline bool mtpIsFalse(const MTPBool &v) {
return !mtpIsTrue(v);
}
// we must validate that MTProto scheme flags don't intersect with client side flags
// and define common bit operators which allow use Type_ClientFlag together with Type::Flag
#define DEFINE_MTP_CLIENT_FLAGS(Type) \
static_assert(static_cast<int32>(Type::Flag::MAX_FIELD) < static_cast<int32>(Type##_ClientFlag::MIN_FIELD), \
"MTProto flags conflict with client side flags!"); \
inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast<int32>(v)); } \
inline Type::Flags operator&(Type::Flags i, Type##_ClientFlag v) { return i & qFlags(v); } \
inline Type::Flags operator&(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) & v; } \
inline Type::Flags &operator&=(Type::Flags &i, Type##_ClientFlag v) { return i &= qFlags(v); } \
inline Type::Flags operator|(Type::Flags i, Type##_ClientFlag v) { return i | qFlags(v); } \
inline Type::Flags operator|(Type::Flag i, Type##_ClientFlag v) { return i | qFlags(v); } \
inline Type::Flags operator|(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) | v; } \
inline Type::Flags operator|(Type##_ClientFlag i, Type::Flag v) { return qFlags(i) | v; } \
inline Type::Flags &operator|=(Type::Flags &i, Type##_ClientFlag v) { return i |= qFlags(v); } \
inline Type::Flags operator~(Type##_ClientFlag v) { return ~qFlags(v); }
// we use the same flags field for some additional client side flags
enum class MTPDmessage_ClientFlag : int32 {
// message has links for "shared links" indexing
f_has_text_links = (1 << 30),
// message is a group migrate (group -> supergroup) service message
f_is_group_migrate = (1 << 29),
// message needs initDimensions() + resize() + paint()
f_pending_init_dimensions = (1 << 28),
// message needs resize() + paint()
f_pending_resize = (1 << 27),
// message needs paint()
f_pending_paint = (1 << 26),
// message is attached to previous one when displaying the history
f_attach_to_previous = (1 << 25),
// message is attached to next one when displaying the history
f_attach_to_next = (1 << 24),
// message was sent from inline bot, need to re-set media when sent
f_from_inline_bot = (1 << 23),
// message has a switch inline keyboard button, need to return to inline
f_has_switch_inline_button = (1 << 22),
// message is generated on the client side and should be unread
f_clientside_unread = (1 << 21),
// update this when adding new client side flags
MIN_FIELD = (1 << 21),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDmessage)
enum class MTPDreplyKeyboardMarkup_ClientFlag : int32 {
// none (zero) markup
f_zero = (1 << 30),
// markup just wants a text reply
f_force_reply = (1 << 29),
// markup keyboard is inline
f_inline = (1 << 28),
// markup has a switch inline keyboard button
f_has_switch_inline_button = (1 << 27),
// update this when adding new client side flags
MIN_FIELD = (1 << 27),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDreplyKeyboardMarkup)
enum class MTPDstickerSet_ClientFlag : int32 {
// old value for sticker set is not yet loaded flag
f_not_loaded__old = (1 << 31),
// sticker set is not yet loaded
f_not_loaded = (1 << 30),
// sticker set is one of featured (should be saved locally)
f_featured = (1 << 29),
// sticker set is an unread featured set
f_unread = (1 << 28),
// special set like recent or custom stickers
f_special = (1 << 27),
// update this when adding new client side flags
MIN_FIELD = (1 << 27),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet)
extern const MTPReplyMarkup MTPnullMarkup;
extern const MTPVector<MTPMessageEntity> MTPnullEntities;
extern const MTPMessageFwdHeader MTPnullFwdHeader;
QString stickerSetTitle(const MTPDstickerSet &s);
inline bool mtpRequestData::isSentContainer(const mtpRequest &request) { // "request-like" wrap for msgIds vector
if (request->size() < 9) return false;
return (!request->msDate && !(*request)[6]); // msDate = 0, seqNo = 0
}
inline bool mtpRequestData::isStateRequest(const mtpRequest &request) {
if (request->size() < 9) return false;
return (mtpTypeId((*request)[8]) == mtpc_msgs_state_req);
}
inline bool mtpRequestData::needAck(const mtpRequest &request) {
if (request->size() < 9) return false;
return mtpRequestData::needAckByType((*request)[8]);
}
inline bool mtpRequestData::needAckByType(mtpTypeId type) {
switch (type) {
case mtpc_msg_container:
case mtpc_msgs_ack:
case mtpc_http_wait:
case mtpc_bad_msg_notification:
case mtpc_msgs_all_info:
case mtpc_msgs_state_info:
case mtpc_msg_detailed_info:
case mtpc_msg_new_detailed_info:
return false;
}
return true;
}

View File

@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/core_types.h"
#include "mtproto/type_utils.h"
#include "mtproto/session.h"
#include "core/single_timer.h"
#include "mtproto/mtp_instance.h"

View File

@ -0,0 +1,25 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "mtproto/type_utils.h"
const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_flags(0), MTP_vector<MTPKeyboardButtonRow>(0));
const MTPVector<MTPMessageEntity> MTPnullEntities = MTP_vector<MTPMessageEntity>(0);
const MTPMessageFwdHeader MTPnullFwdHeader = MTP_messageFwdHeader(MTP_flags(0), MTPint(), MTPint(), MTPint(), MTPint(), MTPstring());

View File

@ -0,0 +1,130 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "scheme.h"
inline MTPbool MTP_bool(bool v) {
return v ? MTP_boolTrue() : MTP_boolFalse();
}
inline bool mtpIsTrue(const MTPBool &v) {
return v.type() == mtpc_boolTrue;
}
inline bool mtpIsFalse(const MTPBool &v) {
return !mtpIsTrue(v);
}
// we must validate that MTProto scheme flags don't intersect with client side flags
// and define common bit operators which allow use Type_ClientFlag together with Type::Flag
#define DEFINE_MTP_CLIENT_FLAGS(Type) \
static_assert(static_cast<int32>(Type::Flag::MAX_FIELD) < static_cast<int32>(Type##_ClientFlag::MIN_FIELD), \
"MTProto flags conflict with client side flags!"); \
inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast<int32>(v)); } \
inline Type::Flags operator&(Type::Flags i, Type##_ClientFlag v) { return i & qFlags(v); } \
inline Type::Flags operator&(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) & v; } \
inline Type::Flags &operator&=(Type::Flags &i, Type##_ClientFlag v) { return i &= qFlags(v); } \
inline Type::Flags operator|(Type::Flags i, Type##_ClientFlag v) { return i | qFlags(v); } \
inline Type::Flags operator|(Type::Flag i, Type##_ClientFlag v) { return i | qFlags(v); } \
inline Type::Flags operator|(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) | v; } \
inline Type::Flags operator|(Type##_ClientFlag i, Type::Flag v) { return qFlags(i) | v; } \
inline Type::Flags &operator|=(Type::Flags &i, Type##_ClientFlag v) { return i |= qFlags(v); } \
inline Type::Flags operator~(Type##_ClientFlag v) { return ~qFlags(v); }
// we use the same flags field for some additional client side flags
enum class MTPDmessage_ClientFlag : int32 {
// message has links for "shared links" indexing
f_has_text_links = (1 << 30),
// message is a group migrate (group -> supergroup) service message
f_is_group_migrate = (1 << 29),
// message needs initDimensions() + resize() + paint()
f_pending_init_dimensions = (1 << 28),
// message needs resize() + paint()
f_pending_resize = (1 << 27),
// message needs paint()
f_pending_paint = (1 << 26),
// message is attached to previous one when displaying the history
f_attach_to_previous = (1 << 25),
// message is attached to next one when displaying the history
f_attach_to_next = (1 << 24),
// message was sent from inline bot, need to re-set media when sent
f_from_inline_bot = (1 << 23),
// message has a switch inline keyboard button, need to return to inline
f_has_switch_inline_button = (1 << 22),
// message is generated on the client side and should be unread
f_clientside_unread = (1 << 21),
// update this when adding new client side flags
MIN_FIELD = (1 << 21),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDmessage)
enum class MTPDreplyKeyboardMarkup_ClientFlag : int32 {
// none (zero) markup
f_zero = (1 << 30),
// markup just wants a text reply
f_force_reply = (1 << 29),
// markup keyboard is inline
f_inline = (1 << 28),
// markup has a switch inline keyboard button
f_has_switch_inline_button = (1 << 27),
// update this when adding new client side flags
MIN_FIELD = (1 << 27),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDreplyKeyboardMarkup)
enum class MTPDstickerSet_ClientFlag : int32 {
// old value for sticker set is not yet loaded flag
f_not_loaded__old = (1 << 31),
// sticker set is not yet loaded
f_not_loaded = (1 << 30),
// sticker set is one of featured (should be saved locally)
f_featured = (1 << 29),
// sticker set is an unread featured set
f_unread = (1 << 28),
// special set like recent or custom stickers
f_special = (1 << 27),
// update this when adding new client side flags
MIN_FIELD = (1 << 27),
};
DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet)
extern const MTPReplyMarkup MTPnullMarkup;
extern const MTPVector<MTPMessageEntity> MTPnullEntities;
extern const MTPMessageFwdHeader MTPnullFwdHeader;

View File

@ -291,6 +291,8 @@
<(src_loc)/mtproto/session.h
<(src_loc)/mtproto/special_config_request.cpp
<(src_loc)/mtproto/special_config_request.h
<(src_loc)/mtproto/type_utils.cpp
<(src_loc)/mtproto/type_utils.h
<(src_loc)/overview/overview_layout.cpp
<(src_loc)/overview/overview_layout.h
<(src_loc)/platform/linux/linux_desktop_environment.cpp