diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index c6eecf928b..ff712278f2 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -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; diff --git a/Telegram/SourceFiles/chat_helpers/stickers.cpp b/Telegram/SourceFiles/chat_helpers/stickers.cpp index 9840e8b918..067e0ec4f3 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers.cpp @@ -524,7 +524,7 @@ void FeaturedSetsReceived(const QVector &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> GetEmojiListFromSet(gsl::not_null> GetEmojiListFromSet(gsl::not_null::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 \n' + methodBodies += 'void MTP' + name + '::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 \n' + methodBodies += 'void MTP' + name + '::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 \n'; - funcsText += 'class MTP' + Name + ' : public MTPBoxed > {\n'; - funcsText += 'public:\n'; - funcsText += '\tMTP' + Name + '() = default;\n'; - funcsText += '\tMTP' + Name + '(const MTP' + name + ' &v) : MTPBoxed >(v) {\n\t}\n'; - if (len(prms) > len(trivialConditions)): - funcsText += '\tMTP' + Name + '(' + ', '.join(prmsStr) + ') : MTPBoxed >(MTP' + name + '(' + ', '.join(prmsNames) + ')) {\n\t}\n'; - funcsText += '};\n'; + funcsText += 'using MTP' + Name + ' = MTPBoxed>;\n'; else: - funcsText += 'class MTP' + Name + ' : public MTPBoxed {\n'; - funcsText += 'public:\n'; - funcsText += '\tMTP' + Name + '() = default;\n'; - funcsText += '\tMTP' + Name + '(const MTP' + name + ' &v) : MTPBoxed(v) {\n\t}\n'; - if (len(prms) > len(trivialConditions)): - funcsText += '\tMTP' + Name + '(' + ', '.join(prmsStr) + ') : MTPBoxed(MTP' + name + '(' + ', '.join(prmsNames) + ')) {\n\t}\n'; - funcsText += '};\n'; + funcsText += 'using MTP' + Name + ' = MTPBoxed;\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;\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;\n'; dataText += '\tfriend inline Flags operator~(Flag v) { return QFlag(~static_cast(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();\n'; - constructsInline += '}\n'; + constructsBodies += '\tt_assert(_type == mtpc_' + name + ');\n'; + constructsBodies += '\treturn queryData();\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;\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;\n\ using StagesFlags = QVector;\n\ \n\ diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h index 6c10c67b9a..a6ecb85876 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h @@ -84,7 +84,7 @@ private: Over = 0x01, DeleteOver = 0x02, }; - Q_DECLARE_FLAGS(StateFlags, StateFlag); + using StateFlags = QFlags; StateFlags _state; friend inline StateFlags operator~(StateFlag flag) { return ~StateFlags(flag); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index b6be5f2e7f..0076c9c0be 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -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; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h index 1275c7c336..07113b9ce0 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h @@ -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 { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 9c8036e085..bcf7bba534 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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) { diff --git a/Telegram/SourceFiles/mtproto/connection.h b/Telegram/SourceFiles/mtproto/connection.h index 8ae4aed3da..fa317c62b7 100644 --- a/Telegram/SourceFiles/mtproto/connection.h +++ b/Telegram/SourceFiles/mtproto/connection.h @@ -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" diff --git a/Telegram/SourceFiles/mtproto/connection_abstract.h b/Telegram/SourceFiles/mtproto/connection_abstract.h index b2aeab3dfd..ad13427fd2 100644 --- a/Telegram/SourceFiles/mtproto/connection_abstract.h +++ b/Telegram/SourceFiles/mtproto/connection_abstract.h @@ -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 { diff --git a/Telegram/SourceFiles/mtproto/connection_auto.h b/Telegram/SourceFiles/mtproto/connection_auto.h index 6ce0eda821..ff5375f911 100644 --- a/Telegram/SourceFiles/mtproto/connection_auto.h +++ b/Telegram/SourceFiles/mtproto/connection_auto.h @@ -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 { diff --git a/Telegram/SourceFiles/mtproto/connection_http.h b/Telegram/SourceFiles/mtproto/connection_http.h index 6c06da25cf..a3a92971f8 100644 --- a/Telegram/SourceFiles/mtproto/connection_http.h +++ b/Telegram/SourceFiles/mtproto/connection_http.h @@ -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 { diff --git a/Telegram/SourceFiles/mtproto/connection_tcp.h b/Telegram/SourceFiles/mtproto/connection_tcp.h index e638d14688..b57175be72 100644 --- a/Telegram/SourceFiles/mtproto/connection_tcp.h +++ b/Telegram/SourceFiles/mtproto/connection_tcp.h @@ -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" diff --git a/Telegram/SourceFiles/mtproto/core_types.cpp b/Telegram/SourceFiles/mtproto/core_types.cpp index 86ddccd07c..9ae542deff 100644 --- a/Telegram/SourceFiles/mtproto/core_types.cpp +++ b/Telegram/SourceFiles/mtproto/core_types.cpp @@ -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(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(0)); -const MTPVector MTPnullEntities = MTP_vector(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; -} diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 4eaeb45e11..caa8860043 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -42,8 +42,7 @@ using mtpTypeId = uint32; class mtpRequestData; class mtpRequest : public QSharedPointer { public: - mtpRequest() { - } + mtpRequest() = default; explicit mtpRequest(mtpRequestData *ptr) : QSharedPointer(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; using mtpRequestMap = QMap; using mtpMsgIdsSet = QMap; @@ -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 const DataType &queryData() const { - // Unsafe cast, type should be checked by the caller. - t_assert(_data != nullptr); + Expects(_data != nullptr); return static_cast(*_data); } @@ -319,20 +279,16 @@ static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]) template class MTPBoxed : public bareT { public: + using bareT::bareT; MTPBoxed() = default; + MTPBoxed(const MTPBoxed &v) = default; + MTPBoxed &operator=(const MTPBoxed &v) = default; MTPBoxed(const bareT &v) : bareT(v) { } - MTPBoxed(const MTPBoxed &v) : bareT(v) { - } - MTPBoxed &operator=(const bareT &v) { *((bareT*)this) = v; return *this; } - MTPBoxed &operator=(const MTPBoxed &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(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 &a, const MTPvector &b) { // Human-readable text serialization -template -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(Type::Flag::MAX_FIELD) < static_cast(Type##_ClientFlag::MIN_FIELD), \ - "MTProto flags conflict with client side flags!"); \ -inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast(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 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; -} diff --git a/Telegram/SourceFiles/mtproto/facade.h b/Telegram/SourceFiles/mtproto/facade.h index 9e0c24c7bf..85bfdb4af7 100644 --- a/Telegram/SourceFiles/mtproto/facade.h +++ b/Telegram/SourceFiles/mtproto/facade.h @@ -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" diff --git a/Telegram/SourceFiles/mtproto/type_utils.cpp b/Telegram/SourceFiles/mtproto/type_utils.cpp new file mode 100644 index 0000000000..021ffaf4c5 --- /dev/null +++ b/Telegram/SourceFiles/mtproto/type_utils.cpp @@ -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(0)); +const MTPVector MTPnullEntities = MTP_vector(0); +const MTPMessageFwdHeader MTPnullFwdHeader = MTP_messageFwdHeader(MTP_flags(0), MTPint(), MTPint(), MTPint(), MTPint(), MTPstring()); diff --git a/Telegram/SourceFiles/mtproto/type_utils.h b/Telegram/SourceFiles/mtproto/type_utils.h new file mode 100644 index 0000000000..974e72bc33 --- /dev/null +++ b/Telegram/SourceFiles/mtproto/type_utils.h @@ -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(Type::Flag::MAX_FIELD) < static_cast(Type##_ClientFlag::MIN_FIELD), \ + "MTProto flags conflict with client side flags!"); \ +inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast(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 MTPnullEntities; +extern const MTPMessageFwdHeader MTPnullFwdHeader; diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 7d4d11c072..a738e8702b 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -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