0) { $depth += $add_depth; } if ($depth <= $target_depth) { if ($add_depth > 0) { $namespace_begin .= $line; } else { $namespace_end .= $line; } } if ($add_depth < 0) { $depth += $add_depth; } if ($is_static) { $common .= $current; } else { $functions[] = $current; } $common .= $line; $current = ''; $is_static = false; $in_define = false; continue; } if (strpos($line, '#undef') === 0 && !trim($current)) { continue; } if ($in_comment && strpos($line, '*/') === 0) { $in_comment = false; continue; } if (strpos($line, '/*') === 0) { $in_comment = true; } if ($in_comment) { continue; } if ($depth !== $target_depth) { $common .= $line; continue; } if (strpos($line, 'static ') === 0 && $depth === $target_depth) { $is_static = true; } if (!trim($current) && strpos($line, '#define ') === 0) { $is_static = true; $in_define = true; } $current .= $line; if ((strpos($line, '}') === 0 || ($in_define && !trim($line)) || preg_match('/^[a-z].*;\s*$/i', $line)) && $depth === $target_depth) { # block end if ($is_static) { $common .= $current; } else { $functions[] = $current; } $current = ''; $is_static = false; $in_define = false; } } $current = trim($current); if (!empty($current)) { fwrite(STDERR, "ERROR: $current".PHP_EOL); exit(); } if (count($functions) < $chunks) { fwrite(STDERR, "ERROR: file is too small to be split more".PHP_EOL); return; } $deps = array(); // all functions from the same subarray must be in the same file $parents = array(); foreach ($functions as $i => $f) { if (preg_match_all('/(?J)create_handler<(?[A-Z][A-Za-z]*)>|'. '(?[A-Z][A-Za-z]*) (final )?: public (Td::ResultHandler|Request)|'. '(CREATE_REQUEST|CREATE_NO_ARGS_REQUEST)[(](?[A-Z][A-Za-z]*)|'. '(?complete_pending_preauthentication_requests)|'. '(?get_message_history_slice)|'. '(Up|Down)load(?!ManagerCallback)[a-zA-Z]+C(?allback)|(up|down)load_[a-z_]*_c(?allback)_|'. '(?lazy_to_json)|'. '(?LogEvent)[^sA]|'. '(?parse)[(]|'. '(?store)[(]/', $f, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $name = $match['name']; if ($name === 'parse' || $name === 'store') { if ($is_generated) { continue; } $name = 'LogEvent'; } $deps[$name][] = $i; } } $parents[$i] = $i; } foreach ($deps as $func_ids) { foreach ($func_ids as $func_id) { disjoint_set_union($parents, $func_ids[0], $func_id); } } $sets = array(); $set_sizes = array(); foreach ($functions as $i => $f) { $parent = disjoint_set_find($parents, $i); if (!isset($sets[$parent])) { $sets[$parent] = ''; $set_sizes[$parent] = 0; } $sets[$parent] .= $f; $set_sizes[$parent] += preg_match('/Td::~?Td/', $f) ? 1000000 : strlen($f); } arsort($set_sizes); $files = array_fill(0, $chunks, ''); $file_sizes = array_fill(0, $chunks, 0); foreach ($set_sizes as $parent => $size) { $file_id = array_search(min($file_sizes), $file_sizes); $files[$file_id] .= $sets[$parent]; $file_sizes[$file_id] += $size; } foreach ($files as $n => $f) { $new_content = $common.$namespace_begin.$f.$namespace_end; $std_methods = array(); preg_match_all('/std::[a-z_0-9]*|td::unique(?!_)/', $new_content, $std_methods); $std_methods = array_unique($std_methods[0]); $needed_std_headers = array(); $type_headers = array( 'std::move' => '', 'std::vector' => '', 'std::string' => '', 'std::uint32_t' => '', 'std::int32_t' => '', 'std::int64_t' => '', 'td::unique' => 'algorithm', 'std::count_if' => 'algorithm', 'std::fill' => 'algorithm', 'std::find' => 'algorithm', 'std::is_sorted' => 'algorithm', 'std::lower_bound' => 'algorithm', 'std::max' => 'algorithm', 'std::merge' => 'algorithm', 'std::min' => 'algorithm', 'std::partial_sort' => 'algorithm', 'std::partition' => 'algorithm', 'std::remove' => 'algorithm', 'std::reverse' => 'algorithm', 'std::rotate' => 'algorithm', 'std::sort' => 'algorithm', 'std::stable_sort' => 'algorithm', 'std::upper_bound' => 'algorithm', 'std::abs' => 'cmath', 'std::isfinite' => 'cmath', 'std::function' => 'functional', 'std::greater' => 'functional', 'std::reference_wrapper' => 'functional', 'std::make_move_iterator' => 'iterator', 'std::numeric_limits' => 'limits', 'std::map' => 'map', 'std::multimap' => 'map', 'std::make_shared' => 'memory', 'std::shared_ptr' => 'memory', 'std::multiset' => 'set', 'std::set' => 'set', 'std::get' => 'tuple', 'std::make_tuple' => 'tuple', 'std::tie' => 'tuple', 'std::tuple' => 'tuple', 'std::decay_t' => 'type_traits', 'std::is_same' => 'type_traits', 'std::unordered_map' => 'unordered_map', 'std::unordered_set' => 'unordered_set', 'std::make_pair' => 'utility', 'std::pair' => 'utility', 'std::swap' => 'utility'); foreach ($type_headers as $type => $header) { if (in_array($type, $std_methods)) { $std_methods = array_diff($std_methods, array($type)); if ($header && !in_array($header, $needed_std_headers)) { $needed_std_headers[] = $header; } } } if (!$std_methods) { // know all needed std headers $new_content = preg_replace_callback( '/#include <([a-z_]*)>/', function ($matches) use ($needed_std_headers) { if (in_array($matches[1], $needed_std_headers)) { return $matches[0]; } return ''; }, $new_content ); } if (!preg_match('/Td::~?Td/', $new_content)) { // destructor Td::~Td needs to see definitions of all forward-declared classes $td_methods = array( 'AccentColorId' => 'AccentColorId', 'account_manager[_(-](?![.]get[(][)])|AccountManager[^;>]' => 'AccountManager', 'animations_manager[_(-](?![.]get[(][)])|AnimationsManager[^;>]' => 'AnimationsManager', 'attach_menu_manager[_(-](?![.]get[(][)])|AttachMenuManager[^;>]' => 'AttachMenuManager', 'audios_manager[_(-](?![.]get[(][)])|AudiosManager' => 'AudiosManager', 'auth_manager[_(-](?![.]get[(][)])|AuthManager' => 'AuthManager', 'AutoDownloadSettings|[a-z_]*auto_download_settings' => 'AutoDownloadSettings', 'autosave_manager[_(-](?![.]get[(][)])|AutosaveManager' => 'AutosaveManager', 'BackgroundId' => 'BackgroundId', 'background_manager[_(-](?![.]get[(][)])|BackgroundManager' => 'BackgroundManager', 'BackgroundType' => 'BackgroundType', 'BotMenuButton|[a-z_]*_menu_button' => 'BotMenuButton', 'boost_manager[_(-](?![.]get[(][)])|BoostManager' => 'BoostManager', 'bot_info_manager[_(-](?![.]get[(][)])|BotInfoManager' => 'BotInfoManager', 'callback_queries_manager[_(-](?![.]get[(][)])|CallbackQueriesManager' => 'CallbackQueriesManager', 'CallId' => 'CallId', 'call_manager[_(-](?![.]get[(][)])|CallManager' => 'CallManager', 'ChannelId' => 'ChannelId', 'ChatId' => 'ChatId', 'common_dialog_manager[_(-](?![.]get[(][)])|CommonDialogManager' => 'CommonDialogManager', 'contacts_manager[_(-](?![.]get[(][)])|ContactsManager([^ ;.]| [^*])' => 'ContactsManager', 'country_info_manager[_(-](?![.]get[(][)])|CountryInfoManager' => 'CountryInfoManager', 'CustomEmojiId' => 'CustomEmojiId', 'device_token_manager[_(-](?![.]get[(][)])|DeviceTokenManager' => 'DeviceTokenManager', 'DialogAction[^M]' => 'DialogAction', 'dialog_action_manager[_(-](?![.]get[(][)])|DialogActionManager' => 'DialogActionManager', 'DialogFilter[^A-Z]' => 'DialogFilter', 'DialogFilterId' => 'DialogFilterId', 'dialog_filter_manager[_(-](?![.]get[(][)])|DialogFilterManager' => 'DialogFilterManager', 'DialogId' => 'DialogId', 'dialog_invite_link_manager[_(-](?![.]get[(][)])|DialogInviteLinkManager' => 'DialogInviteLinkManager', 'DialogListId' => 'DialogListId', 'DialogLocation' => 'DialogLocation', 'dialog_manager[_(-](?![.]get[(][)])|DialogManager' => 'DialogManager', 'DialogParticipantFilter' => 'DialogParticipantFilter', 'dialog_participant_manager[_(-](?![.]get[(][)])|DialogParticipantManager' => 'DialogParticipantManager', 'DialogSource' => 'DialogSource', 'documents_manager[_(-](?![.]get[(][)])|DocumentsManager' => 'DocumentsManager', 'download_manager[_(-](?![.]get[(][)])|DownloadManager[^C]' => 'DownloadManager', 'DownloadManagerCallback' => 'DownloadManagerCallback', 'EmailVerification' => 'EmailVerification', 'EmojiGroup' => 'EmojiGroup', 'EmojiStatus|[a-z_]*_emoji_status' => 'EmojiStatus', 'file_reference_manager[_(-](?![.]get[(][)])|FileReferenceManager|file_references[)]' => 'FileReferenceManager', 'file_manager[_(-](?![.]get[(][)])|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager', 'FolderId' => 'FolderId', 'forum_topic_manager[_(-](?![.]get[(][)])|ForumTopicManager' => 'ForumTopicManager', 'game_manager[_(-](?![.]get[(][)])|GameManager' => 'GameManager', 'G[(][)]|Global[^A-Za-z]' => 'Global', 'GlobalPrivacySettings' => 'GlobalPrivacySettings', 'GroupCallId' => 'GroupCallId', 'group_call_manager[_(-](?![.]get[(][)])|GroupCallManager' => 'GroupCallManager', 'hashtag_hints[_(-](?![.]get[(][)])|HashtagHints' => 'HashtagHints', 'inline_queries_manager[_(-](?![.]get[(][)])|InlineQueriesManager' => 'InlineQueriesManager', 'language_pack_manager[_(-]|LanguagePackManager' => 'LanguagePackManager', 'link_manager[_(-](?![.]get[(][)])|LinkManager' => 'LinkManager', 'LogeventIdWithGeneration|add_log_event|delete_log_event|get_erase_log_event_promise|parse_time|store_time' => 'logevent/LogEventHelper', 'MessageCopyOptions' => 'MessageCopyOptions', 'MessageForwardInfo|LastForwardedMessageInfo|forward_info' => 'MessageForwardInfo', 'MessageFullId' => 'MessageFullId', 'MessageId' => 'MessageId', 'message_import_manager[_(-](?![.]get[(][)])|MessageImportManager' => 'MessageImportManager', 'MessageLinkInfo' => 'MessageLinkInfo', 'MessageReaction|UnreadMessageReaction|[a-z_]*message[a-z_]*reaction' => 'MessageReaction', '[a-z_]*_message_sender' => 'MessageSender', 'messages_manager[_(-](?![.]get[(][)])|MessagesManager' => 'MessagesManager', 'MessageThreadInfo' => 'MessageThreadInfo', 'MessageTtl' => 'MessageTtl', 'notification_manager[_(-](?![.]get[(][)])|NotificationManager|notifications[)]' => 'NotificationManager', 'notification_settings_manager[_(-](?![.]get[(][)])|NotificationSettingsManager' => 'NotificationSettingsManager', 'option_manager[_(-](?![.]get[(][)])|OptionManager' => 'OptionManager', 'password_manager[_(-](?![.]get[(][)])|PasswordManager' => 'PasswordManager', '[a-z_]*phone_number_manager[_(-](?![.]get[(][)])|PhoneNumberManager' => 'PhoneNumberManager', 'PhotoSizeSource' => 'PhotoSizeSource', 'poll_manager[_(-](?![.]get[(][)])|PollManager' => 'PollManager', 'privacy_manager[_(-](?![.]get[(][)])|PrivacyManager' => 'PrivacyManager', 'PublicDialogType|get_public_dialog_type' => 'PublicDialogType', 'ReactionListType|[a-z_]*_reaction_list_type' => 'ReactionListType', 'reaction_manager[_(-](?![.]get[(][)])|ReactionManager' => 'ReactionManager', 'ReactionType|[a-z_]*_reaction_type' => 'ReactionType', 'RequestActor|RequestOnceActor' => 'RequestActor', 'saved_messages_manager[_(-](?![.]get[(][)])|SavedMessagesManager' => 'SavedMessagesManager', 'ScopeNotificationSettings|[a-z_]*_scope_notification_settings' => 'ScopeNotificationSettings', 'SecretChatActor' => 'SecretChatActor', 'secret_chats_manager[_(-]|SecretChatsManager' => 'SecretChatsManager', 'secure_manager[_(-](?![.]get[(][)])|SecureManager' => 'SecureManager', 'SentEmailCode' => 'SentEmailCode', 'sponsored_message_manager[_(-](?![.]get[(][)])|SponsoredMessageManager' => 'SponsoredMessageManager', 'state_manager[_(-](?![.]get[(][)])|StateManager' => 'StateManager', 'statistics_manager[_(-](?![.]get[(][)])|StatisticsManager' => 'StatisticsManager', 'StickerSetId' => 'StickerSetId', 'stickers_manager[_(-](?![.]get[(][)])|StickersManager' => 'StickersManager', 'storage_manager[_(-](?![.]get[(][)])|StorageManager' => 'StorageManager', 'StoryId' => 'StoryId', 'StoryListId' => 'StoryListId', 'story_manager[_(-](?![.]get[(][)])|StoryManager' => 'StoryManager', 'SuggestedAction|[a-z_]*_suggested_action' => 'SuggestedAction', 'td_api' => 'td_api', 'td_db[(][)]|TdDb[^A-Za-z]' => 'TdDb', 'telegram_api' => 'telegram_api', 'theme_manager[_(-](?![.]get[(][)])|ThemeManager' => 'ThemeManager', 'time_zone_manager[_(-](?![.]get[(][)])|TimeZoneManager' => 'TimeZoneManager', 'TopDialogCategory|get_top_dialog_category' => 'TopDialogCategory', 'top_dialog_manager[_(-](?![.]get[(][)])|TopDialogManager' => 'TopDialogManager', 'translation_manager[_(-](?![.]get[(][)])|TranslationManager' => 'TranslationManager', 'transcription_manager[_(-](?![.]get[(][)])|TranscriptionManager' => 'TranscriptionManager', 'updates_manager[_(-](?![.]get[(][)])|UpdatesManager|get_difference[)]|updateSentMessage|dummyUpdate' => 'UpdatesManager', 'UserId' => 'UserId', 'video_notes_manager[_(-](?![.]get[(][)])|VideoNotesManager' => 'VideoNotesManager', 'videos_manager[_(-](?![.]get[(][)])|VideosManager' => 'VideosManager', 'voice_notes_manager[_(-](?![.]get[(][)])|VoiceNotesManager' => 'VoiceNotesManager', 'WebPageId(Hash)?' => 'WebPageId', 'web_pages_manager[_(-](?![.]get[(][)])|WebPagesManager' => 'WebPagesManager'); foreach ($td_methods as $pattern => $header) { if (strpos($cpp_name, $header) !== false) { continue; } $include_name = '#include "td/telegram/'.$header.'.h"'; if (strpos($new_content, $include_name) !== false && preg_match('/[^a-zA-Z0-9_]('.$pattern.')/', str_replace($include_name, '', $new_content)) === 0) { $new_content = str_replace($include_name, '', $new_content); } } } else { $new_content = preg_replace_callback( '|#include "[a-z_A-Z/0-9.]*"|', function ($matches) { if (strpos($matches[0], "Manager") !== false || strpos($matches[0], "HashtagHints") !== false || strpos($matches[0], "Td.h") !== false) { return $matches[0]; } return ''; }, $new_content ); } if (!file_exists($new_files[$n]) || file_get_contents($new_files[$n]) !== $new_content) { echo "Writing file ".$new_files[$n].PHP_EOL; file_put_contents($new_files[$n], $new_content); } } } if (in_array('--help', $argv) || in_array('-h', $argv)) { echo "Usage: php SplitSource.php [OPTION]...\n". "Splits some source files to reduce a maximum amount of RAM needed for compiling a single file.\n". " -u, --undo Undo all source code changes.\n". " -h, --help Show this help.\n"; exit(2); } $undo = in_array('--undo', $argv) || in_array('-u', $argv); $files = array('td/telegram/ContactsManager' => 20, 'td/telegram/MessagesManager' => 50, 'td/telegram/NotificationManager' => 10, 'td/telegram/StickersManager' => 10, 'td/telegram/Td' => 50, 'td/generate/auto/td/telegram/td_api' => 10, 'td/generate/auto/td/telegram/td_api_json' => 10, 'td/generate/auto/td/telegram/telegram_api' => 10); foreach ($files as $file => $chunks) { split_file($file, $chunks, $undo); }